Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F66441079
pmapooc.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
Mon, Jun 10, 13:27
Size
9 KB
Mime Type
text/x-c
Expires
Wed, Jun 12, 13:27 (2 d)
Engine
blob
Format
Raw Data
Handle
18222947
Attached To
R10977 RADIANCE Photon Map
pmapooc.c
View Options
/*
======================================================================
Photon map interface to out-of-core octree
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: pmapooc.c,v 1.2 2020/11/10 01:08:56 u-no-hoo Exp u-no-hoo $
*/
#include "pmapdata.h" /* Includes pmapooc.h */
#include "source.h"
#include "otspecial.h"
#include "oocsort.h"
#include "oocbuild.h"
/* PHOTON MAP BUILD ROUTINES ------------------------------------------ */
/* Returns photon position as sorting key for OOC_Octree & friends (notably
* for Morton code generation).
* !!! XXX: Uses type conversion from float via TEMPORARY storage;
* !!! THIS IS NOT THREAD SAFE!
* !!! RETURNED KEY PERSISTS ONLY IF COPIED BEFORE NEXT CALL! */
RREAL *OOC_PhotonKey (const void *p)
{
static FVECT photonPos; /* Temp storage for type conversion */
VCOPY(photonPos, ((Photon*)p) -> pos);
return photonPos;
}
#ifdef DEBUG_OOC
static void OOC_CheckKeys (FILE *file, const OOC_Octree *oct)
{
Photon p, lastp;
RREAL *key;
OOC_MortonIdx zIdx, lastzIdx = 0;
rewind(file);
memset(&lastp, 0, sizeof(lastp));
while (fread(&p, sizeof(p), 1, file) > 0) {
key = OOC_PhotonKey(&p);
zIdx = OOC_KEY2MORTON(key, oct);
if (zIdx < lastzIdx)
error(INTERNAL, "photons not sorted");
if (zIdx == lastzIdx) {
sprintf(errmsg, "identical key %021ld "
"for [%.9f, %.9f, %.9f]\tand [%.9f, %.9f, %.9f]",
zIdx, lastp.pos [0], lastp.pos [1], lastp.pos [2],
p.pos [0], p.pos [1], p.pos [2]);
error(WARNING, errmsg);
}
lastzIdx = zIdx;
memcpy(&lastp, &p, sizeof(p));
}
}
#endif
void OOC_BuildPhotonMap (struct PhotonMap *pmap, unsigned numProc)
{
FILE *leafFile;
char leafFname [1024];
FVECT d, octOrg;
int i;
RREAL octSize = 0;
/* Determine octree size and origin from pmap extent and init octree */
VCOPY(octOrg, pmap -> minPos);
VSUB(d, pmap -> maxPos, pmap -> minPos);
for (i = 0; i < 3; i++)
if (octSize < d [i])
octSize = d [i];
if (octSize < FTINY)
error(INTERNAL, "zero octree size in OOC_BuildPhotonMap");
/* Derive leaf filename from photon map and open file */
strncpy(leafFname, pmap -> fileName, sizeof(leafFname));
strncat(leafFname, PMAP_OOC_LEAFSUFFIX,
sizeof(leafFname) - strlen(leafFname) - 1);
if (!(leafFile = fopen(leafFname, "w+b")))
error(SYSTEM, "failed to open leaf file in OOC_BuildPhotonMap");
#ifdef DEBUG_OOC
eputs("Sorting photons by Morton code...\n");
#endif
/* Sort photons in heapfile by Morton code and write to leaf file */
if (OOC_Sort(pmap -> heap, leafFile, PMAP_OOC_NUMBLK, PMAP_OOC_BLKSIZE,
numProc, sizeof(Photon), octOrg, octSize, OOC_PhotonKey))
error(INTERNAL, "failed out-of-core photon sort in OOC_BuildPhotonMap");
/* Init and build octree */
OOC_Init(&pmap -> store, sizeof(Photon), octOrg, octSize, OOC_PhotonKey,
leafFile);
#ifdef DEBUG_OOC
eputs("Checking leaf file consistency...\n");
OOC_CheckKeys(leafFile, &pmap -> store);
eputs("Building out-of-core octree...\n");
#endif
if (!OOC_Build(&pmap -> store, PMAP_OOC_LEAFMAX, PMAP_OOC_MAXDEPTH))
error(INTERNAL, "failed out-of-core octree build in OOC_BuildPhotonMap");
#ifdef DEBUG_OOC
eputs("Checking out-of-core octree consistency...\n");
if (OOC_Check(&pmap -> store, OOC_ROOT(&pmap -> store),
octOrg, octSize, 0))
error(INTERNAL, "inconsistent out-of-core octree; Time4Harakiri");
#endif
}
/* PHOTON MAP I/O ROUTINES ------------------------------------------ */
int OOC_SavePhotons (const struct PhotonMap *pmap, FILE *out)
{
return OOC_SaveOctree(&pmap -> store, out);
}
int OOC_LoadPhotons (struct PhotonMap *pmap, FILE *nodeFile)
{
FILE *leafFile;
char leafFname [1024];
/* Derive leaf filename from photon map and open file */
strncpy(leafFname, pmap -> fileName, sizeof(leafFname));
strncat(leafFname, PMAP_OOC_LEAFSUFFIX,
sizeof(leafFname) - strlen(leafFname) - 1);
if (!(leafFile = fopen(leafFname, "r")))
error(SYSTEM, "failed to open leaf file in OOC_LoadPhotons");
if (OOC_LoadOctree(&pmap -> store, nodeFile, OOC_PhotonKey, leafFile))
return -1;
return 0;
}
/* PHOTON MAP SEARCH ROUTINES ------------------------------------------ */
void OOC_InitFindPhotons (struct PhotonMap *pmap)
{
if (OOC_InitNearest(
&pmap -> squeue, pmap -> maxGather + 1, sizeof(Photon)
))
error(SYSTEM, "can't allocate photon search queue");
#ifdef PMAP_PHOTONFLOW
if (isVolumePmap(pmap) && photonFlow)
initPhotonPaths(pmap);
#endif
}
static void OOC_InitPhotonCache (struct PhotonMap *pmap)
/* Initialise OOC photon cache */
{
static char warn = 1;
if (!pmap -> store.cache && !pmap -> numDensity) {
if (pmapCacheSize > 0) {
const unsigned pageSize = pmapCachePageSize * pmap -> maxGather,
numPages = pmapCacheSize / pageSize;
/* Allocate & init I/O cache in octree */
pmap -> store.cache = malloc(sizeof(OOC_Cache));
if (!pmap -> store.cache ||
OOC_CacheInit(
pmap -> store.cache, numPages, pageSize, sizeof(Photon)
)) {
error(SYSTEM, "failed OOC photon map cache init");
}
}
else if (warn) {
error(WARNING, "OOC photon map cache DISABLED");
warn = 0;
}
}
}
int OOC_FindPhotons (
struct PhotonMap *pmap, const FVECT pos, const FVECT norm
)
{
OOC_SearchFilterCallback filt;
OOC_SearchFilterState filtState;
#ifdef PMAP_PHOTONFLOW
OOC_SearchAttribCallback paths, *pathsPtr = NULL;
#endif
float n [3];
/* Lazily init OOC cache */
if (!pmap -> store.cache)
OOC_InitPhotonCache(pmap);
/* Set up filter callback */
if (norm)
VCOPY(n, norm);
filtState.pmap = pmap;
filtState.norm = norm ? n : NULL;
filt.state = &filtState;
filt.filtFunc = filterPhoton;
/* Get sought light source modifier from pmap -> lastContribOrg if
precomputing contribution photon */
filtState.srcMod = isContribPmap(pmap) ?
findmaterial(source [pmap -> lastContribOrg.srcIdx].so) : NULL;
#ifdef PMAP_PHOTONFLOW
if (isVolumePmap(pmap) && photonFlow) {
/* Set up path ID callback */
paths.state = pmap;
paths.findFunc = findPhotonPath;
paths.addFunc = addPhotonPath;
paths.delFunc = deletePhotonPath;
paths.checkFunc = checkPhotonPaths;
pathsPtr = &paths;
resetPhotonPaths(pmap);
}
pmap -> maxDist2 = OOC_FindNearest(
&pmap -> store, OOC_ROOT(&pmap -> store), 0,
pmap -> store.org, pmap -> store.size, pos, &filt, pathsPtr,
&pmap -> squeue, pmap -> maxDist2
);
#else
pmap -> maxDist2 = OOC_FindNearest(
&pmap -> store, OOC_ROOT(&pmap -> store), 0,
pmap -> store.org, pmap -> store.size, pos, &filt, NULL,
&pmap -> squeue, pmap -> maxDist2
);
#endif /* PMAP_PHOTONFLOW */
if (pmap -> maxDist2 < 0)
error(INTERNAL, "failed k-NN photon lookup in OOC_FindPhotons");
/* Return success or failure (empty queue => none found) */
return pmap -> squeue.tail ? 0 : -1;
}
int OOC_Find1Photon (
struct PhotonMap* pmap, const FVECT pos, const FVECT norm, Photon *photon
)
{
OOC_SearchFilterCallback filt;
OOC_SearchFilterState filtState;
float n [3], maxDist2;
/* Lazily init OOC cache */
if (!pmap -> store.cache)
OOC_InitPhotonCache(pmap);
/* Set up filter callback */
if (norm)
VCOPY(n, norm);
filtState.pmap = pmap;
filtState.norm = norm ? n : NULL;
filtState.srcMod = NULL;
filt.state = &filtState;
filt.filtFunc = filterPhoton;
maxDist2 = OOC_Find1Nearest(
&pmap -> store, OOC_ROOT(&pmap -> store), 0,
pmap -> store.org, pmap -> store.size,pos,
&filt, photon, pmap -> maxDist2
);
if (maxDist2 < 0)
error(INTERNAL, "failed 1-NN photon lookup in OOC_Find1Photon");
if (maxDist2 >= pmap -> maxDist2)
/* No photon found => failed */
return -1;
else {
/* Set photon distance => success */
pmap -> maxDist2 = maxDist2;
return 0;
}
}
/* PHOTON ACCESS ROUTINES ------------------------------------------ */
int OOC_GetPhoton (struct PhotonMap *pmap, PhotonIdx idx,
Photon *photon)
{
return OOC_GetData(&pmap -> store, idx, photon);
}
Photon *OOC_GetNearestPhoton (const PhotonSearchQueue *squeue, PhotonIdx idx)
{
return OOC_GetNearest(squeue, idx);
}
PhotonIdx OOC_FirstPhoton (const struct PhotonMap* pmap)
{
return 0;
}
Event Timeline
Log In to Comment