Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F61139365
pmapio.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
Sat, May 4, 19:10
Size
13 KB
Mime Type
text/x-c
Expires
Mon, May 6, 19:10 (2 d)
Engine
blob
Format
Raw Data
Handle
17456196
Attached To
R10977 RADIANCE Photon Map
pmapio.c
View Options
#ifndef lint
static
const
char
RCSid
[]
=
"$Id: pmapio.c,v 2.14 2022/03/03 03:55:13 greg Exp $"
;
#endif
/*
=========================================================================
Photon map portable file I/O
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: pmapio.c,v 2.14 2022/03/03 03:55:13 greg Exp $
*/
#include "pmapio.h"
#include "pmapdiag.h"
#include "pmapcontrib.h"
#include "resolu.h"
#include <sys/stat.h>
extern
char
*
octname
;
void
savePhotonMap
(
const
PhotonMap
*
pmap
,
const
char
*
fname
,
int
argc
,
char
**
argv
)
{
unsigned
j
;
FILE
*
file
;
if
(
!
pmap
||
!
pmap
->
numPhotons
||
!
validPmapType
(
pmap
->
type
))
{
error
(
INTERNAL
,
"attempt to save empty or invalid photon map"
);
return
;
}
if
(
verbose
)
{
sprintf
(
errmsg
,
"Saving %s (%ld photons)
\n
"
,
fname
,
pmap
->
numPhotons
);
eputs
(
errmsg
);
fflush
(
stderr
);
}
if
(
!
(
file
=
fopen
(
fname
,
"wb"
)))
{
sprintf
(
errmsg
,
"can't open photon map file %s"
,
fname
);
error
(
SYSTEM
,
errmsg
);
}
/* Write header */
newheader
(
"RADIANCE"
,
file
);
/* Write command line */
printargs
(
argc
,
argv
,
file
);
/* Include statistics in info text */
fprintf
(
file
,
"NumPhotons
\t
= %ld
\n
"
"AvgFlux
\t\t
= [%.3g, %.3g, %.3g]
\n
"
"Bbox
\t\t
= [%.3g, %.3g, %.3g] [%.3g, %.3g, %.3g]
\n
"
"CoG
\t\t
= [%.3g, %.3g, %.3g]
\n
"
"MaxDist^2
\t
= %.3g
\n
"
"Velocity
\t
= %g / sec
\n
"
"Timespan
\t
= [%g, %g] sec
\n
"
"AvgPathLen
\t
= %.3g
\n
"
,
pmap
->
numPhotons
,
pmap
->
photonFlux
[
0
],
pmap
->
photonFlux
[
1
],
pmap
->
photonFlux
[
2
],
pmap
->
minPos
[
0
],
pmap
->
minPos
[
1
],
pmap
->
minPos
[
2
],
pmap
->
maxPos
[
0
],
pmap
->
maxPos
[
1
],
pmap
->
maxPos
[
2
],
pmap
->
CoG
[
0
],
pmap
->
CoG
[
1
],
pmap
->
CoG
[
2
],
pmap
->
CoGdist
,
pmap
->
velocity
,
pmap
->
minPathLen
/
pmap
->
velocity
,
pmap
->
maxPathLen
/
pmap
->
velocity
,
pmap
->
avgPathLen
);
#ifdef PMAP_CONTRIB
if
(
isContribChildPmap
(
pmap
)
&&
pmap
->
preCompContrib
)
{
/* Child contrib pmap containing precomputed contributions;
append binning params to header */
const
PreComputedContrib
*
preCompContrib
=
(
PreComputedContrib
*
)(
pmap
->
preCompContrib
);
fprintf
(
file
,
"Photon Map contains precomputed %s %s
\n
"
,
#ifdef PMAP_CONTRIB_LOG
"logarithmic"
,
#else
"linear"
,
#endif
pmap
->
contribMode
?
"contributions"
:
"coefficients"
);
if
(
preCompContrib
->
nBins
>
1
)
fprintf
(
file
,
"Num bins
\t
= %u x %u = %u
\n
"
"Num coeffs
\t
= %u/%u compressed detail, %u approx, %u total
\n
"
"Compression
\t
= %.1f%%
\n
"
"mRGBE config
\t
= %d:%d:%d:%d:%d
\n
"
,
preCompContrib
->
scDim
,
preCompContrib
->
scDim
,
preCompContrib
->
nBins
,
preCompContrib
->
nCompressedCoeffs
,
WAVELET_PADD2_NUMDETAIL
(
preCompContrib
->
nNonZeroCoeffs
),
WAVELET_PADD2_NUMAPPROX
,
preCompContrib
->
nCoeffs
,
100
*
(
1
-
(
float
)
preCompContrib
->
nCompressedCoeffs
/
WAVELET_PADD2_NUMDETAIL
(
preCompContrib
->
nNonZeroCoeffs
)
),
mRGBE_MANTBITS
,
mRGBE_MANTBITS
,
mRGBE_MANTBITS
,
mRGBE_EXPBITS
,
mRGBE_DATABITS
);
else
fputs
(
"Binning disabled
\n
"
,
file
);
}
#endif
/* Write format, including human-readable file version */
fputformat
(
pmapFormat
[
pmap
->
type
],
file
);
fprintf
(
file
,
"VERSION=%s
\n
"
,
PMAP_FILEVER
);
/* Empty line = end of header */
putc
(
'\n'
,
file
);
/* Write machine-readable file format version */
putstr
(
PMAP_FILEVER
,
file
);
/* Write 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. */
putint
(
pmap
->
numPhotons
,
PMAP_LONGSIZE
,
file
);
/* Write average photon flux */
for
(
j
=
0
;
j
<
3
;
j
++
)
putflt
(
pmap
->
photonFlux
[
j
],
file
);
/* Write max and min photon positions */
for
(
j
=
0
;
j
<
3
;
j
++
)
{
putflt
(
pmap
->
minPos
[
j
],
file
);
putflt
(
pmap
->
maxPos
[
j
],
file
);
}
/* Write centre of gravity */
for
(
j
=
0
;
j
<
3
;
j
++
)
putflt
(
pmap
->
CoG
[
j
],
file
);
/* Write avg distance to centre of gravity */
putflt
(
pmap
->
CoGdist
,
file
);
/* Save photon's velocity (speed of light in units of scene geometry),
min/max/avg photon path length (= timespan and temporal CoG) */
putflt
(
pmap
->
velocity
,
file
);
putflt
(
pmap
->
minPathLen
,
file
);
putflt
(
pmap
->
maxPathLen
,
file
);
putflt
(
pmap
->
avgPathLen
,
file
);
#ifdef PMAP_CONTRIB
if
(
isContribChildPmap
(
pmap
)
&&
pmap
->
preCompContrib
)
{
/* Child contrib photon map containing per-modifier precomputed
contributions; save mode, number of bins and number of wavelet
coefficients */
PreComputedContrib
*
preCompContrib
=
(
PreComputedContrib
*
)(
pmap
->
preCompContrib
);
putint
(
pmap
->
contribMode
,
sizeof
(
pmap
->
contribMode
),
file
);
putint
(
preCompContrib
->
scDim
,
sizeof
(
preCompContrib
->
scDim
),
file
);
putint
(
preCompContrib
->
coeffDim
,
sizeof
(
preCompContrib
->
coeffDim
),
file
);
putint
(
preCompContrib
->
nNonZeroCoeffs
,
sizeof
(
preCompContrib
->
nNonZeroCoeffs
),
file
);
putint
(
preCompContrib
->
nCompressedCoeffs
,
sizeof
(
preCompContrib
->
nCompressedCoeffs
),
file
);
}
else
if
(
isContribPmap
(
pmap
)
&&
pmap
->
preCompContribTab
)
/* Parent contrib photon map; save child photon maps containing
per-modifier precomputed contributions */
saveContribPhotonMap
(
pmap
,
fname
,
argc
,
argv
);
#endif
/* Save photon storage (except if parent contribution photon map, which
* just acts as a container for its children) */
#ifdef PMAP_OOC
if
(
#ifdef PMAP_CONTRIB
!
isContribPmap
(
pmap
)
&&
#
endif
OOC_SavePhotons
(
pmap
,
file
)
)
{
#else
if
(
kdT_SavePhotons
(
pmap
,
file
))
{
#endif
sprintf
(
errmsg
,
"error writing photon map file %s"
,
fname
);
error
(
SYSTEM
,
errmsg
);
}
fclose
(
file
);
}
PhotonMapType
loadPhotonMap
(
PhotonMap
*
pmap
,
const
char
*
fname
)
{
PhotonMapType
ptype
=
PMAP_TYPE_NONE
;
char
format
[
MAXFMTLEN
];
unsigned
j
;
FILE
*
file
;
if
(
!
pmap
)
return
PMAP_TYPE_NONE
;
if
((
file
=
fopen
(
fname
,
"rb"
))
==
NULL
)
{
sprintf
(
errmsg
,
"can't open photon map file %s"
,
fname
);
error
(
SYSTEM
,
errmsg
);
}
/* Get format string */
strcpy
(
format
,
PMAP_FORMAT_GLOB
);
if
(
checkheader
(
file
,
format
,
NULL
)
!=
1
)
{
sprintf
(
errmsg
,
"photon map file %s has an unknown format"
,
fname
);
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"
,
fname
);
error
(
USER
,
errmsg
);
}
/* Init empty photon map of found type */
initPhotonMap
(
pmap
,
ptype
);
/* Set filename (prefixed by contrib pmap for per-modifier files) */
pmap
->
fileName
=
(
char
*
)
fname
;
/* Get file format version and check for compatibility */
if
(
strcmp
(
getstr
(
format
,
file
),
PMAP_FILEVER
))
error
(
USER
,
"incompatible photon map file format"
);
/* 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. */
pmap
->
numPhotons
=
getint
(
PMAP_LONGSIZE
,
file
);
/* Get average photon flux */
for
(
j
=
0
;
j
<
3
;
j
++
)
pmap
->
photonFlux
[
j
]
=
getflt
(
file
);
/* Get max and min photon positions */
for
(
j
=
0
;
j
<
3
;
j
++
)
{
pmap
->
minPos
[
j
]
=
getflt
(
file
);
pmap
->
maxPos
[
j
]
=
getflt
(
file
);
}
/* Get centre of gravity */
for
(
j
=
0
;
j
<
3
;
j
++
)
pmap
->
CoG
[
j
]
=
getflt
(
file
);
/* Get avg distance to centre of gravity */
pmap
->
CoGdist
=
getflt
(
file
);
/* Get photon's velocity (speed of light in units of scene geometry),
min/max/avg photon path length (= timespan) and temporal CoG */
pmap
->
velocity
=
getflt
(
file
);
pmap
->
minPathLen
=
getflt
(
file
);
pmap
->
maxPathLen
=
getflt
(
file
);
pmap
->
avgPathLen
=
getflt
(
file
);
#ifdef PMAP_CONTRIB
if
(
isContribChildPmap
(
pmap
))
{
/* Per-modifier precomputed contribution (child) photon map;
allocate precomputed contributions, get mode, number of bins,
and number of wavelet coefficients */
PreComputedContrib
*
preCompContrib
=
(
PreComputedContrib
*
)(
pmap
->
preCompContrib
=
malloc
(
sizeof
(
PreComputedContrib
))
);
if
(
!
preCompContrib
)
error
(
SYSTEM
,
"out of memory allocating precomputed contributions"
" in loadPhotonMap()"
);
initPreComputedContrib
(
preCompContrib
);
pmap
->
contribMode
=
getint
(
sizeof
(
pmap
->
contribMode
),
file
);
preCompContrib
->
scDim
=
getint
(
sizeof
(
preCompContrib
->
scDim
),
file
);
preCompContrib
->
coeffDim
=
getint
(
sizeof
(
preCompContrib
->
coeffDim
),
file
);
preCompContrib
->
nNonZeroCoeffs
=
getint
(
sizeof
(
preCompContrib
->
nNonZeroCoeffs
),
file
);
preCompContrib
->
nCompressedCoeffs
=
getint
(
sizeof
(
preCompContrib
->
nCompressedCoeffs
),
file
);
}
else
if
(
isContribPmap
(
pmap
))
/* Parent contrib photon map; load child photon maps containing
per-modifier precomputed contributions */
loadContribPhotonMap
(
pmap
,
fname
);
#endif
/* Load photon storage (except if parent contribution photon map, which
* just acts as a container for its children) */
#ifdef PMAP_OOC
if
(
#ifdef PMAP_CONTRIB
!
isContribPmap
(
pmap
)
&&
#
endif
OOC_LoadPhotons
(
pmap
,
file
)
)
{
#else
if
(
kdT_LoadPhotons
(
pmap
,
file
))
{
#endif
sprintf
(
errmsg
,
"error reading photon map file %s"
,
fname
);
error
(
SYSTEM
,
errmsg
);
}
fclose
(
file
);
return
ptype
;
}
void
savePmaps
(
const
PhotonMap
**
pmaps
,
int
argc
,
char
**
argv
)
/* Wrapper to save all defined photon maps with specified command line */
{
unsigned
t
;
for
(
t
=
0
;
t
<
NUM_PMAP_TYPES
;
t
++
)
{
if
(
pmaps
[
t
])
savePhotonMap
(
pmaps
[
t
],
pmaps
[
t
]
->
fileName
,
argc
,
argv
);
}
}
void
loadPmaps
(
PhotonMap
**
pmaps
,
const
PhotonMapParams
*
parm
)
/* Wrapper to load all photon maps and set their parameters */
{
unsigned
t
;
struct
stat
octstat
,
pmstat
;
PhotonMap
*
pm
;
PhotonMapType
type
;
for
(
t
=
0
;
t
<
NUM_PMAP_TYPES
;
t
++
)
if
(
setPmapParam
(
&
pm
,
parm
+
t
))
{
/* Check if photon map newer than octree */
if
(
pm
->
fileName
&&
octname
&&
!
stat
(
pm
->
fileName
,
&
pmstat
)
&&
!
stat
(
octname
,
&
octstat
)
&&
octstat
.
st_mtime
>
pmstat
.
st_mtime
)
{
sprintf
(
errmsg
,
"photon map in file %s may be stale"
,
pm
->
fileName
);
error
(
USER
,
errmsg
);
}
/* Load photon map from file and get its type */
if
((
type
=
loadPhotonMap
(
pm
,
pm
->
fileName
))
==
PMAP_TYPE_NONE
)
error
(
USER
,
"failed loading photon map"
);
/* Assign to appropriate photon map type (deleting previously
* loaded photon map of same type if necessary) */
if
(
pmaps
[
type
])
{
sprintf
(
errmsg
,
"multiple %s photon maps, dropping previous"
,
pmapName
[
type
]
);
error
(
WARNING
,
errmsg
);
deletePhotons
(
pmaps
[
type
]);
free
(
pmaps
[
type
]);
}
pmaps
[
type
]
=
pm
;
/* Check for valid density estimate bandwidths */
if
((
pm
->
minGather
>
1
||
pm
->
maxGather
>
1
)
&&
(
type
==
PMAP_TYPE_PRECOMP
)
)
{
/* Force bwidth to 1 for precomputed pmap */
error
(
WARNING
,
"ignoring bandwidth for precomp photon map"
);
pm
->
minGather
=
pm
->
maxGather
=
1
;
}
if
((
pm
->
maxGather
>
pm
->
minGather
)
&&
(
type
==
PMAP_TYPE_VOLUME
)
)
{
/* Biascomp for volume pmaps (see volumePhotonDensity() below)
is considered redundant, and there's probably no point in
recovering by using the lower bandwidth, since it's probably
not what the user wants, so bail out. */
sprintf
(
errmsg
,
"bias compensation is not available with %s photon maps"
,
pmapName
[
type
]
);
error
(
USER
,
errmsg
);
}
if
(
pm
->
maxGather
>
pm
->
numPhotons
)
{
/* Clamp lookup bandwidth to total number of photons (minus one,
since density estimate gets extra photon to obtain averaged
radius) */
sprintf
(
errmsg
,
"clamping density estimate bandwidth to %ld"
,
pm
->
numPhotons
);
error
(
WARNING
,
errmsg
);
pm
->
minGather
=
pm
->
maxGather
=
pm
->
numPhotons
-
1
;
}
}
}
Event Timeline
Log In to Comment