Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F85180030
pmapfilt.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, Sep 27, 08:14
Size
11 KB
Mime Type
text/x-c
Expires
Sun, Sep 29, 08:14 (2 d)
Engine
blob
Format
Raw Data
Handle
21132269
Attached To
R10977 RADIANCE Photon Map
pmapfilt.c
View Options
/*
======================================================================
Photon map filter callbacks for nearest neighbour search
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")
(c) Tokyo University of Science,
supported by the JSPS Grants-in-Aid for Scientific Research
(KAKENHI JP19KK0115, "Three-Dimensional Light Flow")
======================================================================
$Id: pmapfilt.c,v 1.2 2020/11/16 22:28:23 u-no-hoo Exp u-no-hoo $
*/
#include "pmapfilt.h"
#include "pmapdata.h"
#include "pmap.h"
#include "random.h"
#include "source.h"
#include "otspecial.h"
int
filterPhoton
(
const
void
*
rec
,
const
void
*
state
)
/* Filter callback for photon kNN search */
{
const
Photon
*
photon
=
rec
;
const
PhotonSearchFilterState
*
filtState
=
state
;
const
PhotonMap
*
pmap
=
filtState
->
pmap
;
/* Reject photon if normal faces away (ignored for volume photons) with
* tolerance to account for perturbation; note photon normal is coded
* in range [-127,127], hence we factor this in */
if
(
filtState
->
norm
&&
DOT
(
filtState
->
norm
,
photon
->
norm
)
<=
PMAP_NORM_TOL
*
127
*
frandom
()
)
return
0
;
#ifdef PMAP_PHOTONFLOW
if
(
isLightFlowPmap
(
pmap
)
&&
hemiLightFlow
&&
!
sphericalIrrad
)
{
/* Hemispherical lookup mode; omit lightflow photons which pass normal
test above but lie behind the plane. This reduces bias near solid
boundaries (scene cube limits or actual geometry), in which case no
photons may be present behind the plane.
NOTE: filtstate->norm is REVERSED in this mode since photon->norm
(=photon direction here) points TOWARDS the receiving surface! */
FVECT
photonVec
;
VSUB
(
photonVec
,
photon
->
pos
,
filtState
->
pos
);
if
(
DOT
(
filtState
->
norm
,
photonVec
)
>
FTINY
)
return
0
;
}
#endif
if
(
isContribPmap
(
pmap
))
{
/* Lookup in contribution photon map; accept photon only if its
emitting light source modifier matches that of the filter state
(if defined). */
if
(
filtState
->
srcMod
)
{
const
int
srcIdx
=
photonSrcIdx
(
pmap
,
photon
);
if
(
srcIdx
<
0
||
srcIdx
>=
nsources
)
error
(
INTERNAL
,
"invalid light source index in photon map"
);
if
(
filtState
->
srcMod
!=
findmaterial
(
source
[
srcIdx
].
so
))
return
0
;
}
/* Reject non-caustic photon if lookup for caustic contribs */
if
(
pmap
->
lookupCaustic
&&
!
photon
->
caustic
)
return
0
;
}
/* Accept photon */
return
1
;
}
#ifdef PMAP_PATHFILT
/* Length of key strings for photon path LUT (plus terminator) */
#define PMAP_PATHKEYLEN ((sizeof(PhotonOrigin) + 1 << 1) + 1)
void
initPhotonPaths
(
void
*
state
)
/* Lazily allocate and initialise photon path ID lookup table and
* associate key buffer */
{
PhotonMap
*
pmap
=
state
;
if
(
!
pmap
->
pathLUT
)
{
/* Allocate and init photon path ID lookup table of same size as
* search queue */
LUTAB
initLUT
=
LU_SINIT
(
NULL
,
NULL
);
if
(
!
(
pmap
->
pathLUT
=
malloc
(
sizeof
(
LUTAB
))))
error
(
SYSTEM
,
"failed photon path lookup table allocation"
);
memcpy
(
pmap
->
pathLUT
,
&
initLUT
,
sizeof
(
initLUT
));
if
(
!
lu_init
(
pmap
->
pathLUT
,
pmap
->
squeue
.
len
))
error
(
INTERNAL
,
"failed photon path lookup table init"
);
}
if
(
!
pmap
->
pathLUTKeys
)
{
/* Allocate key buffer of same size as search queue (+1 for
* scratchpad at tail) */
unsigned
k
,
maxKeys
=
pmap
->
squeue
.
len
+
1
;
pmap
->
pathLUTKeys
=
(
char
**
)
calloc
(
maxKeys
,
sizeof
(
char
*
));
for
(
k
=
0
;
k
<
maxKeys
;
k
++
)
if
(
pmap
->
pathLUTKeys
||
!
(
pmap
->
pathLUTKeys
[
k
]
=
(
char
*
)
malloc
(
PMAP_PATHKEYLEN
))
)
error
(
SYSTEM
,
"failed photon path LUT key buffer allocation"
);
}
/* Reset photon path ID key buffer */
pmap
->
numPathLUTKeys
=
0
;
}
static
char
*
photonPathKey
(
const
Photon
*
photon
,
char
*
key
)
{
/* Generate LUT key from photon path ID. Writes transposed hex string
into specified key buffer. */
PhotonOrigin
pathId1
=
photon
->
org
;
unsigned
char
pathId2
=
photon
->
proc
;
char
*
kp
=
key
;
unsigned
i
;
for
(
i
=
sizeof
(
PhotonOrigin
)
<<
1
;
i
;
*
kp
++
=
(
pathId1
&
0x0f
)
+
'A'
,
pathId1
>>=
4
,
i
--
);
for
(
i
=
sizeof
(
unsigned
char
)
<<
1
;
i
;
*
kp
++
=
(
pathId2
&
0x0f
)
+
'A'
,
pathId2
>>=
4
,
i
--
);
*
kp
++
=
'\0'
;
return
key
;
}
int
checkPhotonPaths
(
const
void
*
state
)
/* Run sanity check on photon path ID lookup table */
{
const
PhotonMap
*
pmap
=
state
;
const
PhotonSearchQueue
*
squeue
=
&
pmap
->
squeue
;
const
PhotonSearchQueueNode
*
squeueNode
;
const
Photon
*
photon
;
const
LUENT
*
lutEntry
;
unsigned
squeueIdx
;
char
key
[
PMAP_PATHKEYLEN
];
if
(
!
pmap
->
pathLUT
||
!
pmap
->
pathLUTKeys
)
error
(
INTERNAL
,
"photon path lookup table not initialised"
);
for
(
squeueIdx
=
0
,
squeueNode
=
squeue
->
node
;
squeueIdx
<
squeue
->
tail
;
squeueIdx
++
,
squeueNode
++
)
{
photon
=
getNearestPhoton
(
squeue
,
squeueNode
->
idx
);
photonPathKey
(
photon
,
key
);
lutEntry
=
lu_find
(
pmap
->
pathLUT
,
key
);
if
(
!
lutEntry
||
!
lutEntry
->
key
||
strcmp
(
lutEntry
->
key
,
key
))
error
(
CONSISTENCY
,
"invalid key in photon path LUT check"
);
if
(
!
lutEntry
->
data
||
(
PhotonSearchQueueNode
*
)
lutEntry
->
data
!=
squeueNode
)
error
(
CONSISTENCY
,
"invalid data in photon path LUT check"
);
}
return
0
;
}
/* TODO: REPLACE pathLUTKeys SCRATCHPAD WITH LOCAL ARRAYS??? */
void
**
findPhotonPath
(
const
void
*
rec
,
const
void
*
state
)
/* Photon path callback for k-NN search to map photon path IDs to search
* queue nodes via a lookup table. State points to the associated photon
* map containing the path lookup table. Returns modifiable pointer to data
* field of found LUT entry, which in turn points to the search queue node
* for the corresponding record. If no entry exists for the path ID, NULL
* is returned. */
{
const
Photon
*
photon
=
rec
;
const
PhotonMap
*
pmap
=
state
;
char
*
key
;
LUENT
*
lutEntry
;
if
(
!
pmap
->
pathLUT
||
!
pmap
->
pathLUTKeys
)
error
(
INTERNAL
,
"photon path lookup table not initialised"
);
/* Generate key for photon's path and write into next free slot in key
buffer (using it as scratchpad) */
key
=
photonPathKey
(
photon
,
pmap
->
pathLUTKeys
[
pmap
->
numPathLUTKeys
]
);
#ifdef PMAP_DEBUGPATHS
printf
(
"%s "
,
key
);
#endif
/* Look up attribute for generated key, set last LUT entry in state */
if
(
!
(
lutEntry
=
lu_find
(
pmap
->
pathLUT
,
key
)))
/* Outta mammaries */
error
(
SYSTEM
,
"failed photon path lookup entry allocation"
);
return
(
void
**
)(
lutEntry
->
data
?
&
lutEntry
->
data
:
NULL
);
}
void
addPhotonPath
(
const
void
*
rec
,
void
*
data
,
void
*
state
)
/* Photon path callback for k-NN search to add photon path IDs to lookup
table entries. State points to the associated photon map containing the
path lookup table. The new lookup table entry is initialised with the
specified data pointer */
{
const
Photon
*
photon
=
rec
;
PhotonMap
*
pmap
=
state
;
char
*
key
;
LUENT
*
lutEntry
;
if
(
!
pmap
->
pathLUT
||
!
pmap
->
pathLUTKeys
)
error
(
INTERNAL
,
"photon path lookup table not initialised"
);
/* Generate key for photon's path and write into next free slot in key
buffer */
key
=
photonPathKey
(
photon
,
pmap
->
pathLUTKeys
[
pmap
->
numPathLUTKeys
]
);
/* Find free LUT entry for generated key */
if
(
!
(
lutEntry
=
lu_find
(
pmap
->
pathLUT
,
key
)))
/* Outta mammaries */
error
(
SYSTEM
,
"failed photon path lookup entry allocation"
);
if
(
lutEntry
->
data
)
/* Occupied */
error
(
INTERNAL
,
"attempt to overwrite photon path lookup entry"
);
#ifdef PMAP_DEBUGPATHS
printf
(
"%s add
\n
"
,
key
);
#endif
/* Set data and key fields, advance key buffer tail */
lutEntry
->
data
=
data
;
lutEntry
->
key
=
pmap
->
pathLUTKeys
[
pmap
->
numPathLUTKeys
];
if
(
pmap
->
numPathLUTKeys
>
pmap
->
squeue
.
tail
)
/* Number of keys (and distinct path IDs) can never exceed the number
of photons currently in the search queue (+1 for scratchpad) */
error
(
INTERNAL
,
"photon path lookup table key overflow"
);
else
pmap
->
numPathLUTKeys
++
;
}
static
char
emptyKey
=
'\0'
;
void
deletePhotonPath
(
const
void
*
rec
,
void
*
state
)
/* Photon path callback for k-NN search to delete photon path IDs from
lookup table. State points to the associated photon map containing the
path ID lookup table. */
{
const
Photon
*
photon
=
rec
;
PhotonMap
*
pmap
=
state
;
LUENT
*
lutEntry
;
char
*
delKey
,
*
relocKey
;
if
(
!
pmap
->
pathLUT
||
!
pmap
->
pathLUTKeys
)
error
(
INTERNAL
,
"photon path lookup table not initialised"
);
/* Generate key for photon's path and write into scratchpad at key buffer
tail (will be overwritten) */
delKey
=
photonPathKey
(
photon
,
pmap
->
pathLUTKeys
[
pmap
->
numPathLUTKeys
]
);
#ifdef PMAP_DEBUGPATHS
printf
(
"%s del
\n
"
,
delKey
);
#endif
/* Find photon's LUT entry, check if valid, and get its key buffer slot */
lutEntry
=
lu_find
(
pmap
->
pathLUT
,
delKey
);
if
(
!
lutEntry
||
!
lutEntry
->
key
||
!
lutEntry
->
data
)
error
(
CONSISTENCY
,
"attempt to delete empty photon path LUT entry"
);
/* Delete photon LUT entry */
lu_delete
(
pmap
->
pathLUT
,
delKey
);
delKey
=
lutEntry
->
key
;
lutEntry
->
key
=
&
emptyKey
;
/* ??? */
/* Decrement key buffer tail and get last valid key */
relocKey
=
pmap
->
pathLUTKeys
[
--
pmap
->
numPathLUTKeys
];
if
(
delKey
!=
relocKey
)
{
/* Reclaim deleted photon's key buffer slot by overwriting with last
valid key */
memcpy
(
delKey
,
relocKey
,
PMAP_PATHKEYLEN
);
relocKey
=
delKey
;
#ifdef PMAP_DEBUGPATHS
printf
(
"%s reloc
\n
"
,
relocKey
);
#endif
/* Update the LUT entry owning the relocated key to point to its new
position in the overwritten slot, again checking for validity */
lutEntry
=
lu_find
(
pmap
->
pathLUT
,
relocKey
);
if
(
!
lutEntry
||
!
lutEntry
->
key
||
!
lutEntry
->
data
)
error
(
CONSISTENCY
,
"attempt to delete empty photon path LUT entry"
);
lutEntry
->
key
=
relocKey
;
}
}
int
clearPhotonPath
(
const
LUENT
*
lutEntry
,
void
*
lut
)
/* Clear entry in photon path ID lookup table */
{
#ifdef PMAP_DEBUGPATHS
printf
(
"%s clr
\n
"
,
lutEntry
->
key
);
#endif
lu_delete
(
lut
,
lutEntry
->
key
);
/* Apologies to Don Gregorio for abusing his LUT here... */
((
LUENT
*
)
lutEntry
)
->
key
=
&
emptyKey
;
return
0
;
}
void
resetPhotonPaths
(
void
*
state
)
/* Reset (clear) all entries in photon path ID lookup table */
{
PhotonMap
*
pmap
=
state
;
if
(
!
pmap
->
pathLUT
)
error
(
INTERNAL
,
"photon path lookup table not initialised"
);
lu_doall
(
pmap
->
pathLUT
,
clearPhotonPath
,
pmap
->
pathLUT
);
/* Reset photon path ID key buffer */
pmap
->
numPathLUTKeys
=
0
;
}
#endif
/* PMAP_PATHFILT */
Event Timeline
Log In to Comment