Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F59547268
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
Tue, Apr 23, 10:24
Size
9 KB
Mime Type
text/x-c
Expires
Thu, Apr 25, 10:24 (2 d)
Engine
blob
Format
Raw Data
Handle
17208364
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)
======================================================================
$Id: pmapooc.c,v 1.6 2020/04/08 15:14:21 rschregle Exp $
*/
#include "pmapdata.h" /* Includes pmapooc.h */
#include "source.h"
#include "otspecial.h"
#include "oocsort.h"
#include "oocbuild.h"
/* Returns photon position as sorting key for OOC_Octree & friends (notably
* for Morton code generation).
* !!! 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 int 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");
return -1;
}
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));
}
return 0;
}
#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
}
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;
}
void OOC_InitFindPhotons (struct PhotonMap *pmap)
{
if (OOC_InitNearest(&pmap -> squeue, pmap -> maxGather + 1,
sizeof(Photon)))
error(SYSTEM, "can't allocate photon search queue");
}
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;
}
}
}
typedef struct {
const PhotonMap *pmap;
const float *norm;
} OOC_FilterData;
int OOC_FilterPhoton (void *p, void *fd)
/* Filter callback for photon kNN search, used by OOC_FindNearest() */
{
const Photon *photon = p;
const OOC_FilterData *filtData = fd;
const PhotonMap *pmap = filtData -> 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 (filtData -> norm &&
DOT(filtData->norm, photon->norm) <= PMAP_NORM_TOL * 127 * frandom())
return 0;
if (isContribPmap(pmap)) {
/* Lookup in contribution photon map; filter according to emitting
* light source if contrib list set, else accept all */
if (pmap -> srcContrib) {
OBJREC *srcMod;
const int srcIdx = photonSrcIdx(pmap, photon);
if (srcIdx < 0 || srcIdx >= nsources)
error(INTERNAL, "invalid light source index in photon map");
srcMod = findmaterial(source [srcIdx].so);
/* Reject photon if contributions from light source which emitted
* it are not sought */
if (!lu_find(pmap -> srcContrib, srcMod -> oname) -> data)
return 0;
}
/* Reject non-caustic photon if lookup for caustic contribs */
if (pmap -> lookupCaustic && !photon -> caustic)
return 0;
}
/* Accept photon */
return 1;
}
int OOC_FindPhotons (struct PhotonMap *pmap, const FVECT pos, const FVECT norm)
{
OOC_SearchFilter filt;
OOC_FilterData filtData;
float n [3];
/* Lazily init OOC cache */
if (!pmap -> store.cache)
OOC_InitPhotonCache(pmap);
/* Set up filter callback */
filtData.pmap = pmap;
if (norm)
VCOPY(n, norm);
filtData.norm = norm ? n : NULL;
filt.data = &filtData;
filt.func = OOC_FilterPhoton;
pmap -> maxDist2 = OOC_FindNearest(&pmap -> store,
OOC_ROOT(&pmap -> store), 0,
pmap -> store.org, pmap -> store.size,
pos, &filt, &pmap -> squeue,
pmap -> maxDist2);
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_SearchFilter filt;
OOC_FilterData filtData;
float n [3], maxDist2;
/* Lazily init OOC cache */
if (!pmap -> store.cache)
OOC_InitPhotonCache(pmap);
/* Set up filter callback */
filtData.pmap = pmap;
if (norm)
VCOPY(n, norm);
filtData.norm = norm ? n : NULL;
filt.data = &filtData;
filt.func = OOC_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;
}
}
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