Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F74195637
pmcontrib2a.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
Fri, Jul 26, 10:16
Size
24 KB
Mime Type
text/x-c
Expires
Sun, Jul 28, 10:16 (1 d, 21 h)
Engine
blob
Format
Raw Data
Handle
19353157
Attached To
R10977 RADIANCE Photon Map
pmcontrib2a.c
View Options
#ifndef lint
static
const
char
RCSid
[]
=
"$Id$"
;
#endif
/*
=========================================================================
Photon map routines for precomputed light source contributions.
This is the main photon distribution routine used by mkpmap.
!!! THIS EXPERIMENTAL VERSION USES IMPORTANCE SAMPLING OF LIGHT SOURCE
!!! FLUX, SIMILAR TO distribPhotons(). CONSEQUENTLY, IT DOES NOT
!!! MAINTAIN A LIST OF PER-SOURCE FLUX, AND MAY UNDERESTIMATE SOURCES
!!! WITH LOW CONTRIBUTIONS.
Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
(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")
=========================================================================
$Id$
*/
#include "pmapcontrib.h"
#ifdef PMAP_CONTRIB
#include "pmapdiag.h"
#include "pmaprand.h"
#include "pmapmat.h"
#include "pmaproi.h"
#include "pmapsrc.h"
#include "pmapio.h"
#include "otspecial.h"
#if NIX
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#endif
/* Defs for photon emission counter array passed by sub-processes to parent
* via shared memory */
typedef
unsigned
long
PhotonContribCnt
;
/* Indices for photon emission counter array: num photons stored and num
* emitted per source */
#define PHOTONCNT_NUMPHOT 0
#define PHOTONCNT_NUMEMIT 1
#define PHOTONCNT_SIZE 2
void
distribPhotonContrib
(
PhotonMap
*
pmap
,
LUTAB
*
contribTab
,
unsigned
numContribs
,
int
*
contribMode
,
unsigned
numProc
)
{
EmissionMap
emap
;
char
errmsg2
[
128
],
shmFname
[
PMAP_TMPFNLEN
];
unsigned
srcIdx
,
proc
;
int
shmFile
,
stat
,
pid
;
double
totalFlux
=
0
;
/* Total emitted source flux */
unsigned
long
*
photonCnt
;
/* Photon counter array */
FILE
**
contribSrcHeap
=
NULL
;
char
**
contribSrcHeapFname
=
NULL
;
PhotonContribSourceIdx
*
contribSrcOfs
=
NULL
;
pid_t
procPids
[
PMAP_MAXPROC
];
if
(
!
pmap
)
error
(
USER
,
"no contribution photon map specified"
);
if
(
!
nsources
)
error
(
USER
,
"no light sources"
);
if
(
nsources
>
PMAP_MAXSRCIDX
)
error
(
USER
,
"too many light sources"
);
if
(
!
contribTab
||
!
numContribs
)
error
(
USER
,
"no modifiers specified for contribution photon map"
);
/* ===================================================================
* INITIALISATION - Set up emission and scattering funcs
* =================================================================== */
emap
.
samples
=
NULL
;
emap
.
src
=
NULL
;
emap
.
maxPartitions
=
MAXSPART
;
emap
.
partitions
=
(
unsigned
char
*
)
malloc
(
emap
.
maxPartitions
>>
1
);
if
(
!
emap
.
partitions
)
error
(
USER
,
"can't allocate source partitions in distribPhotonContrib"
);
/* Initialise contrib photon map */
initPhotonMap
(
pmap
,
PMAP_TYPE_CONTRIB
);
initPmapContribTab
(
contribTab
,
contribMode
);
pmap
->
contribMode
=
*
contribMode
;
initPmapContrib
(
pmap
);
initPhotonHeap
(
pmap
);
initPhotonEmissionFuncs
();
initPhotonScatterFuncs
();
/* Per-subprocess target counts */
if
(
!
(
pmap
->
distribTarget
/=
numProc
))
error
(
INTERNAL
,
"no photons to distribute in distribPhotonContrib"
);
/* Get photon ports from modifier list */
getPhotonPorts
(
photonPortList
);
/* Get photon sensor modifiers */
getPhotonSensors
(
photonSensorList
);
/* Get polyhedral regions of interest */
getPolyROIs
(
pmapROImodList
);
#if NIX
/* Set up shared mem for photon counters (zeroed by ftruncate) */
strcpy
(
shmFname
,
PMAP_TMPFNAME
);
shmFile
=
mkstemp
(
shmFname
);
if
(
shmFile
<
0
||
ftruncate
(
shmFile
,
PHOTONCNT_SIZE
)
<
0
)
error
(
SYSTEM
,
"failed shared mem init in distribPhotonContrib"
);
photonCnt
=
mmap
(
NULL
,
PHOTONCNT_SIZE
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
shmFile
,
0
);
if
(
photonCnt
==
MAP_FAILED
)
error
(
SYSTEM
,
"failed mapping shared memory in distribPhotonContrib"
);
#else
photonCnt
[
PHOTONCNT_NUMPHOT
]
=
photonCnt
[
PHOTONCNT_NUMEMIT
]
=
0
;
#endif
/* NIX */
if
(
verbose
)
{
sprintf
(
errmsg
,
"
\n
Integrating flux from %d sources"
,
nsources
);
if
(
photonPorts
)
{
sprintf
(
errmsg2
,
" via %d ports"
,
numPhotonPorts
);
strcat
(
errmsg
,
errmsg2
);
}
strcat
(
errmsg
,
"
\n
"
);
eputs
(
errmsg
);
}
/* =============================================================
* FLUX INTEGRATION - Get total flux emitted from sources/ports
* ============================================================= */
for
(
srcIdx
=
0
;
srcIdx
<
nsources
;
srcIdx
++
)
{
unsigned
portCnt
=
0
;
const
OBJREC
*
srcMod
=
findmaterial
(
source
[
srcIdx
].
so
);
/* Skip this source if its contributions are not sought */
if
(
!
lu_find
(
pmapContribTab
,
srcMod
->
oname
)
->
data
)
{
sprintf
(
errmsg
,
"ignoring contributions from source %s"
,
source
[
srcIdx
].
so
->
oname
);
error
(
WARNING
,
errmsg
);
continue
;
}
emap
.
src
=
source
+
srcIdx
;
do
{
/* Need at least one iteration if no ports! */
emap
.
port
=
emap
.
src
->
sflags
&
SDISTANT
?
photonPorts
+
portCnt
:
NULL
;
photonPartition
[
emap
.
src
->
so
->
otype
]
(
&
emap
);
if
(
verbose
)
{
sprintf
(
errmsg
,
"
\t
Integrating flux from source %s "
,
source
[
srcIdx
].
so
->
oname
);
if
(
emap
.
port
)
{
sprintf
(
errmsg2
,
"via port %s "
,
photonPorts
[
portCnt
].
so
->
oname
);
strcat
(
errmsg
,
errmsg2
);
}
sprintf
(
errmsg2
,
"(%lu partitions)
\n
"
,
emap
.
numPartitions
);
strcat
(
errmsg
,
errmsg2
);
eputs
(
errmsg
);
#if NIX
fflush
(
stderr
);
#endif
}
for
(
emap
.
partitionCnt
=
0
;
emap
.
partitionCnt
<
emap
.
numPartitions
;
emap
.
partitionCnt
++
)
{
initPhotonEmission
(
&
emap
,
pdfSamples
);
totalFlux
+=
colorAvg
(
emap
.
partFlux
);
}
portCnt
++
;
}
while
(
portCnt
<
numPhotonPorts
);
}
if
(
totalFlux
<
FTINY
)
error
(
USER
,
"zero flux from light sources"
);
/* Allocate & init per-subprocess contribution source heap files */
contribSrcHeap
=
calloc
(
numProc
,
sizeof
(
FILE
*
));
contribSrcHeapFname
=
calloc
(
numProc
,
sizeof
(
char
*
));
contribSrcOfs
=
calloc
(
numProc
,
sizeof
(
PhotonContribSourceIdx
));
if
(
!
contribSrcHeap
||
!
contribSrcHeapFname
||
!
contribSrcOfs
)
error
(
SYSTEM
,
"failed contribution source heap allocation "
"in distribPhotonContrib()"
);
for
(
proc
=
0
;
proc
<
numProc
;
proc
++
)
{
contribSrcHeapFname
[
proc
]
=
malloc
(
PMAP_TMPFNLEN
);
if
(
!
contribSrcHeapFname
[
proc
])
error
(
SYSTEM
,
"failed contribution source heap file allocation "
"in distribPhotonContrib()"
);
mktemp
(
strcpy
(
contribSrcHeapFname
[
proc
],
PMAP_TMPFNAME
));
if
(
!
(
contribSrcHeap
[
proc
]
=
fopen
(
contribSrcHeapFname
[
proc
],
"w+b"
)))
error
(
SYSTEM
,
"failed opening contribution source heap file "
"in distribPhotonContrib()"
);
}
/* Record start time for progress reports */
repStartTime
=
time
(
NULL
);
if
(
verbose
)
{
sprintf
(
errmsg
,
"
\n
Photon distribution @ %d procs
\n
"
,
numProc
);
eputs
(
errmsg
);
}
/* MAIN LOOP */
for
(
proc
=
0
;
proc
<
numProc
;
proc
++
)
{
#if NIX
if
(
!
(
pid
=
fork
()))
{
/* SUBPROCESS ENTERS HERE; opened and mmapped files inherited */
#else
if
(
1
)
{
/* No subprocess under Windoze */
#endif
/* Local photon counters for this subprocess */
unsigned
passCnt
=
0
,
prePassCnt
=
0
;
unsigned
long
preIncPhotonCnt
,
lastNumPhotons
=
0
,
numEmitted
=
0
,
lastNumEmitted
=
0
;
/* Decorrelate shared photon counter updates to reduce
* contention by setting unique update intervals per subproc */
const
unsigned
photonCntUpdate
=
PMAP_CNTUPDATE
+
proc
;
/* Seed RNGs from PID for decorellated photon distribution */
pmapSeed
(
randSeed
+
proc
,
partState
);
pmapSeed
(
randSeed
+
(
proc
+
1
)
%
numProc
,
emitState
);
pmapSeed
(
randSeed
+
(
proc
+
2
)
%
numProc
,
cntState
);
pmapSeed
(
randSeed
+
(
proc
+
3
)
%
numProc
,
mediumState
);
pmapSeed
(
randSeed
+
(
proc
+
4
)
%
numProc
,
scatterState
);
pmapSeed
(
randSeed
+
(
proc
+
5
)
%
numProc
,
rouletteState
);
#ifdef DEBUG_PMAP
/* Output child process PID after random delay to prevent corrupted
* console output due to race condition */
usleep
(
1e6
*
pmapRandom
(
rouletteState
));
fprintf
(
stderr
,
"Proc %d: PID = %d (waiting 10 sec to attach debugger...)
\n
"
,
proc
,
getpid
()
);
/* Allow time for debugger to attach to child process */
sleep
(
10
);
#endif
/* =============================================================
* 2-PASS PHOTON DISTRIBUTION
* Pass 1 (pre): emit fraction of target photon count
* Pass 2 (main): based on outcome of pass 1, estimate remaining
* number of photons to emit to approximate target
* count
* ============================================================= */
while
(
passCnt
<
2
)
{
double
numEmit
;
if
(
!
passCnt
)
{
/* INIT PASS 1 */
if
(
++
prePassCnt
>
maxPreDistrib
)
{
/* Skip if no photons contributed after sufficient
* iterations */
sprintf
(
errmsg
,
"proc %d: too many prepasses, no photons stored; "
"increase -apD?"
,
proc
);
error
(
USER
,
errmsg
);
break
;
}
/* Num to emit is fraction of target count */
numEmit
=
preDistrib
*
pmap
->
distribTarget
;
}
else
{
/* INIT PASS 2 */
/* Based on the outcome of the predistribution we can now
* figure out how many more photons we have to emit from
* the current source to meet the target count,
* distribTarget. This value is clamped to 0 in case
* the target has already been exceeded in pass 1.
* srcNumEmit and srcNumDistrib is the number of photons
* emitted and distributed (stored) from the current
* source in pass 1, respectively. */
numEmit
=
numEmitted
*
(
pmap
->
numPhotons
?
max
((
float
)
pmap
->
distribTarget
/
pmap
->
numPhotons
,
1.
)
-
1.
:
0.
);
if
(
!
numEmit
)
/* No photons left to distribute in main pass */
break
;
}
/* PHOTON DISTRIBUTION LOOP */
for
(
srcIdx
=
0
;
srcIdx
<
nsources
;
srcIdx
++
)
{
unsigned
portCnt
=
0
;
emap
.
src
=
source
+
srcIdx
;
do
{
/* Need at least one iteration if no ports! */
emap
.
port
=
emap
.
src
->
sflags
&
SDISTANT
?
photonPorts
+
portCnt
:
NULL
;
photonPartition
[
emap
.
src
->
so
->
otype
]
(
&
emap
);
if
(
verbose
&&
!
proc
)
{
/* Output from subproc 0 only to avoid race condition
* on console I/O */
if
(
!
passCnt
)
sprintf
(
errmsg
,
"
\t
PREPASS %d on source %s "
,
prePassCnt
,
source
[
srcIdx
].
so
->
oname
);
else
sprintf
(
errmsg
,
"
\t
MAIN PASS on source %s "
,
source
[
srcIdx
].
so
->
oname
);
if
(
emap
.
port
)
{
sprintf
(
errmsg2
,
"via port %s "
,
photonPorts
[
portCnt
].
so
->
oname
);
strcat
(
errmsg
,
errmsg2
);
}
sprintf
(
errmsg2
,
"(%lu partitions)
\n
"
,
emap
.
numPartitions
);
strcat
(
errmsg
,
errmsg2
);
eputs
(
errmsg
);
#if NIX
fflush
(
stderr
);
#endif
}
for
(
emap
.
partitionCnt
=
0
;
emap
.
partitionCnt
<
emap
.
numPartitions
;
emap
.
partitionCnt
++
)
{
double
partNumEmit
;
unsigned
long
partEmitCnt
;
/* Get photon origin within current source partishunn
* and build emission map */
photonOrigin
[
emap
.
src
->
so
->
otype
]
(
&
emap
);
initPhotonEmission
(
&
emap
,
pdfSamples
);
/* Number of photons to emit from ziss partishunn;
* scale according to its normalised contribushunn to
* the emitted source flux */
partNumEmit
=
numEmit
*
colorAvg
(
emap
.
partFlux
)
/
totalFlux
;
partEmitCnt
=
(
unsigned
long
)
partNumEmit
;
/* Probabilistically account for fractional photons */
if
(
pmapRandom
(
cntState
)
<
partNumEmit
-
partEmitCnt
)
partEmitCnt
++
;
/* Integer counter avoids FP rounding errors during
* iteration */
while
(
partEmitCnt
--
)
{
RAY
photonRay
;
/* Emit photon according to PDF (if any). If
* accepted, allocate associated contribution
* origin, and trace through scene until
* absorbed/leaked; emitPhoton() sets the emitting
* light source index in photonRay */
/* NOTE: rejection sampling skips incrementing the
* emission counter (see below), thus compensating
* for the rejected photons by increasing the photon
* flux in proportion to the lower effective
* emission count.
* BUG: THIS INTERFERES WITH THE PROGRESS COUNTER
* REPORTED TO THE PARENT, AND WITH THE
* PREDISTRIBUTION PASS --> PHOTON DISTRIBUTION WILL
* FINISH EARLY, WITH FEWER PHOTONS THAN TARGETTED!
*/
if
(
!
emitPhoton
(
&
emap
,
&
photonRay
))
continue
;
newPhotonContribSource
(
pmap
,
&
photonRay
,
contribSrcHeap
[
proc
]
);
/* Update local emission counter */
numEmitted
++
;
/* Skip photon if it has an invalid bin. It will
implicitly contribute zero flux, so don't bother
tracing and storing it. However, it counts as
emitted to avoid bias (see enclosing while() loop
and local emission counter update above). */
if
(
pmap
->
lastContribSrc
.
srcBin
<
0
)
continue
;
/* Set subprocess index in photonRay for post-
* distrib contribution source index linearisation;
* this is propagated with the contrib source index
* in photonRay and set for photon hits by
* newPhoton() */
PMAP_SETRAYPROC
(
&
photonRay
,
proc
);
tracePhoton
(
&
photonRay
);
if
(
!
(
partEmitCnt
&&
(
numEmitted
&
photonCntUpdate
)))
{
/* Update global counters shared with siblings
in unique intervals to reduce overhead and
contention;
ALSO WHEN EMITTING FINAL PHOTON FROM THIS
PARTITION, OTHERWISE COUNTERS WILL SKIP LAST
UPDATE, BIASING THE PHOTON FLUX! */
/* Shared photon counter file must be locked! */
shmLock
(
shmFile
,
F_WRLCK
);
/* Differentially increment number emitted using
* local counter numEmitted */
preIncPhotonCnt
=
photonCnt
[
PHOTONCNT_NUMEMIT
];
photonCnt
[
PHOTONCNT_NUMEMIT
]
+=
numEmitted
-
lastNumEmitted
;
lastNumEmitted
=
numEmitted
;
/* Check overflow using pre-increment values */
if
(
photonCnt
[
PHOTONCNT_NUMEMIT
]
<
preIncPhotonCnt
)
{
sprintf
(
errmsg
,
"photon emission counter "
"overflow (was: %ld, is: %ld)"
,
preIncPhotonCnt
,
photonCnt
[
PHOTONCNT_NUMEMIT
]
);
error
(
INTERNAL
,
errmsg
);
}
/* Differentially increment photon counter */
preIncPhotonCnt
=
photonCnt
[
PHOTONCNT_NUMPHOT
];
photonCnt
[
PHOTONCNT_NUMPHOT
]
+=
pmap
->
numPhotons
-
lastNumPhotons
;
lastNumPhotons
=
pmap
->
numPhotons
;
/* Check for photon counter overflow (this could
only happen before an emission counter overflow
if the scene has an absurdly high albedo and/or
very dense geometry) */
if
(
photonCnt
[
PHOTONCNT_NUMPHOT
]
<
preIncPhotonCnt
)
{
sprintf
(
errmsg
,
"photon counter overflow "
"(was: %ld, is: %ld)"
,
preIncPhotonCnt
,
photonCnt
[
PHOTONCNT_NUMPHOT
]
);
error
(
INTERNAL
,
errmsg
);
}
/* Release lock on shared photon counter file! */
shmLock
(
shmFile
,
F_UNLCK
);
}
}
#if !NIX
/* Synchronous progress report on Windoze */
if
(
!
proc
&&
photonRepTime
>
0
&&
time
(
NULL
)
>=
repLastTime
+
photonRepTime
)
{
unsigned
s
;
repComplete
=
pmap
->
distribTarget
*
numProc
;
repProgress
=
photonCnt
[
PHOTONCNT_NUMPHOT
];
for
(
repEmitted
=
0
,
s
=
0
;
s
<
nsources
;
s
++
)
repEmitted
+=
photonCnt
[
numEmitIdx
];
pmapDistribReport
();
}
#endif
}
portCnt
++
;
}
while
(
portCnt
<
numPhotonPorts
);
if
(
!
pmap
->
numPhotons
)
{
/* Double predistrib factor in case no photons were stored
* for this source and redo pass 1 */
preDistrib
*=
2
;
}
else
{
/* Now do pass 2 */
passCnt
++
;
}
}
}
/* Flush heap buffa one final time to prevent data corruption */
flushPhotonHeap
(
pmap
);
/* Flush last contribution origin to origin heap file */
newPhotonContribSource
(
pmap
,
NULL
,
contribSrcHeap
[
proc
]);
/* Heap files closed automatically on exit
fclose(pmap -> heap);
fclose(orgHeap [proc]); */
#ifdef DEBUG_PMAP
sprintf
(
errmsg
,
"Proc %d total %ld photons
\n
"
,
proc
,
pmap
->
numPhotons
);
eputs
(
errmsg
);
fflush
(
stderr
);
#endif
#ifdef PMAP_SIGUSR
signal
(
SIGUSR1
,
SIG_DFL
);
#endif
#if NIX
/* Terminate subprocess */
exit
(
0
);
#endif
}
else
{
/* PARENT PROCESS CONTINUES LOOP ITERATION HERE */
if
(
pid
<
0
)
error
(
SYSTEM
,
"failed to fork subprocess in distribPhotonContrib()"
);
else
/* Saves child process IDs */
procPids
[
proc
]
=
pid
;
}
}
#if NIX
/* PARENT PROCESS CONTINUES HERE */
#ifdef SIGCONT
/* Enable progress report signal handler */
signal
(
SIGCONT
,
pmapDistribReport
);
#endif
/* Wait for subprocesses to complete while reporting progress */
proc
=
numProc
;
while
(
proc
)
{
while
(
waitpid
(
-
1
,
&
stat
,
WNOHANG
)
>
0
)
{
/* Subprocess exited; check status */
if
(
!
WIFEXITED
(
stat
)
||
WEXITSTATUS
(
stat
))
{
/* Exited with error; terminate siblings, clean up & bail out */
for
(
proc
=
0
;
proc
<
numProc
;
proc
++
)
kill
(
procPids
[
proc
],
SIGKILL
);
/* Unmap shared memory, squish mapped file */
munmap
(
photonCnt
,
PHOTONCNT_SIZE
);
close
(
shmFile
);
unlink
(
shmFname
);
error
(
USER
,
"failed photon distribution"
);
}
--
proc
;
}
/* Nod off for a bit and update progress */
sleep
(
1
);
/* Asynchronous progress report from shared subprocess counters */
shmLock
(
shmFile
,
F_RDLCK
);
repProgress
=
photonCnt
[
PHOTONCNT_NUMPHOT
];
pmap
->
numPhotons
=
photonCnt
[
PHOTONCNT_NUMPHOT
];
for
(
repEmitted
=
0
,
srcIdx
=
0
;
srcIdx
<
nsources
;
srcIdx
++
)
{
repEmitted
+=
photonCnt
[
PHOTONCNT_NUMEMIT
];
}
repComplete
=
pmap
->
distribTarget
*
numProc
;
shmLock
(
shmFile
,
F_UNLCK
);
if
(
photonRepTime
>
0
&&
time
(
NULL
)
>=
repLastTime
+
photonRepTime
)
pmapDistribReport
();
#ifdef SIGCONT
else
signal
(
SIGCONT
,
pmapDistribReport
);
#endif
}
#endif
/* NIX */
/* ================================================================
* POST-DISTRIBUTION - Set photon flux and build kd-tree, etc.
* ================================================================ */
#ifdef SIGCONT
/* Reset signal handler */
signal
(
SIGCONT
,
SIG_DFL
);
#endif
free
(
emap
.
samples
);
if
(
!
pmap
->
numPhotons
)
error
(
USER
,
"empty contribution photon map"
);
/* Load per-subprocess contribution sources into pmap -> contribSrc */
/* Dumb compilers apparently need the char** cast */
pmap
->
numContribSrc
=
buildContribSources
(
pmap
,
contribSrcHeap
,
(
char
**
)
contribSrcHeapFname
,
contribSrcOfs
,
numProc
);
if
(
!
pmap
->
numContribSrc
)
error
(
INTERNAL
,
"no contribution sources in contribution photon map"
);
/* Set photon flux */
totalFlux
=
photonCnt
[
PHOTONCNT_NUMEMIT
]
?
totalFlux
/
photonCnt
[
PHOTONCNT_NUMEMIT
]
:
0
;
#if NIX
/* Photon counters no longer needed, unmap shared memory */
munmap
(
photonCnt
,
PHOTONCNT_SIZE
);
close
(
shmFile
);
unlink
(
shmFname
);
#else
free
(
photonCnt
);
#endif
if
(
verbose
)
{
eputs
(
"
\n
Building contribution photon map...
\n
"
);
#if NIX
fflush
(
stderr
);
#endif
}
/* Build underlying data structure; heap is destroyed.
XXX: Photon flux remains unchanged (i.e. normalised) in coefficient
mode, so totalFlux is omitted */
buildPhotonMap
(
pmap
,
pmap
->
contribMode
?
&
totalFlux
:
NULL
,
contribSrcOfs
,
numProc
);
/* Precompute binned photon contributions, init lookup table pmap ->
preCompContribTab containing constituent pre-modifier photon maps */
if
(
verbose
)
eputs
(
"
\n
"
);
preComputeContrib
(
contribPmap
);
/* Free per-subprocess origin heap files */
for
(
proc
=
0
;
proc
<
numProc
;
proc
++
)
free
(
contribSrcHeapFname
[
proc
]);
free
(
contribSrcHeapFname
);
free
(
contribSrcHeap
);
free
(
contribSrcOfs
);
if
(
verbose
)
eputs
(
"
\n
"
);
}
#endif
/* PMAP_CONTRIB */
Event Timeline
Log In to Comment