Page MenuHomec4science

pmaproi.c
No OneTemporary

File Metadata

Created
Tue, May 21, 18:56

pmaproi.c

#ifndef lint
static const char RCSid[] = "$Id$";
#endif
/*
======================================================================
Regions of interest used by mkpmap to constrain location of photons
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$
*/
#include "pmaproi.h"
#include "otspecial.h"
#include "otypes.h"
#include "face.h"
/* Rectangular / spherical regions of interest */
unsigned pmapNumROI = 0;
PhotonMapROI *pmapROI = NULL;
/* Polyhedral regions of interest by modifier */
char *pmapROImodList [MAXSET + 1] = {NULL};
OBJECT polyROIset [PMAP_MAXROI + 1] = {0};
/* Bounding box for polyhedral ROI */
PhotonMapROI polyROIbbox = {
{FHUGE, FHUGE, FHUGE}, {-FHUGE, -FHUGE, -FHUGE}
};
void getPolyROIs (char **roiModList)
/* Find geometry comprising polyhedral regions of interest from modifiers in
* roiModList */
{
OBJECT i, j;
OBJREC *obj, *objMat;
FACE *objFace;
char **lp;
unsigned lastNumPolys = 0, v;
RREAL *objVert;
/* Init poly ROI set */
polyROIset [0] = 0;
if (!roiModList [0])
return;
for (lp = roiModList; *lp; lp++) {
lastNumPolys = polyROIset [0];
for (i = 0; i < nobjects; i++) {
obj = objptr(i);
objMat = findmaterial(obj);
/* Check if object is a polygon and its modifier is in list */
if (objMat && !strcmp(objMat -> oname, *lp) &&
issurface(obj -> otype)
) {
if (obj -> otype == OBJ_FACE) {
if (polyROIset [0] >= PMAP_MAXROI)
error(USER, "too many polyhedral ROI objects");
else {
insertelem(polyROIset, i);
/* Get polygon and iterate over its vertices */
if (objFace = getface(obj)) {
for (v = 0; v < objFace -> nv; v++) {
objVert = VERTEX(objFace, v);
/* Update bounding box with vertex (note hacky
treatment of polyROIbbox.siz as max here) */
for (j = 0; j < 3; j++) {
if (objVert [j] < polyROIbbox.pos [j])
polyROIbbox.pos [j] = objVert [j];
else if (objVert [j] > polyROIbbox.siz [j])
polyROIbbox.siz [j] = objVert [j];
}
}
}
else {
sprintf(errmsg,
"got egg on face extracting vertices for "
"polyhedral ROI modifier %s", *lp
);
error(CONSISTENCY, errmsg);
}
}
}
else {
sprintf(errmsg,
"non-polygonal ROI geometry for modifier %s", *lp
);
error(USER, errmsg);
}
}
}
if (polyROIset [0] == lastNumPolys) {
/* No geometry added for this modifier */
sprintf(errmsg, "no polyhedral ROI geometry for modifier %s", *lp);
error(USER, errmsg);
}
}
if (!polyROIset [0])
/* Made redundant by check above? */
error(USER, "no polyhedral ROI found");
}
int photonInROI (const RAY *photonRay)
/* Returns nonzero if photon defined by photonRay lies in any defined region
* of interest */
{
int inROI = 0, i;
if (pmapNumROI && pmapROI) {
/* Check rectangular / spherical ROIs */
FVECT photonDist;
for (i = 0; i < pmapNumROI; i++) {
VSUB(photonDist, photonRay -> rop, pmapROI [i].pos);
/* NOTE: Size of spherical ROI is _squared_ */
inROI = (PMAP_ROI_ISSPHERE(pmapROI + i)
? DOT(photonDist, photonDist) <= pmapROI [i].siz [0]
: fabs(photonDist [0]) <= pmapROI [i].siz [0] &&
fabs(photonDist [1]) <= pmapROI [i].siz [1] &&
fabs(photonDist [2]) <= pmapROI [i].siz [2]
);
if (inROI)
/* Bail out early, skip remaining ROIs */
return 1;
}
/* Failed inclusion test on all rectangular/spherical ROIs */
return 0;
}
if (polyROIset [0]) {
/* Check polyhedral ROI */
RAY testRay;
int rayFlip = 0;
#if 1
/* Start with quick bounding box test (note hacky treatment of
polyROIbbox.siz as maximum coords here) */
for (i = 0; i < 3; i++) {
if (photonRay -> rop [i] < polyROIbbox.pos [i] ||
photonRay -> rop [i] > polyROIbbox.siz [i]
)
return 0;
}
#endif
/* Init inclusion test ray at photon origin */
rayorigin(&testRay, PRIMARY, NULL, NULL);
testRay.rmax = FHUGE;
/* Now send rays and count number of crossed polygons in ROI set */
do {
if (!rayFlip) {
/* 1st iteration: set up forward test ray from photon hitpoint,
offset slightly in reversed direction to avoid potential
boundary issues with surface-bound (i.e. global, caustic)
photons */
VSUM(testRay.rorg, photonRay -> rop,
photonRay -> rdir, -2 * FTINY
);
VCOPY(testRay.rdir, photonRay -> rdir);
}
else {
/* 2nd iteration: reverse test ray direction from photon
hitpoint. This additional test mitigates issues with
semi-open ROIs */
VCOPY(testRay.rorg, photonRay -> rop);
for (i = 0; i < 3; i++)
testRay.rdir [i] = -photonRay -> rdir [i];
}
/* Follow inclusion test ray until it leaves the scene */
while (localhit(&testRay, &thescene)) {
/* Toggle odd/even number of crossings if intersected object is in
ROI set (note this works since inset() returns 0 or 1!) */
inROI ^= inset(polyROIset, testRay.robj);
/* Update ray origin with intersection for next iteration */
VCOPY(testRay.rorg, testRay.rop);
}
if (!(rayFlip || inROI))
/* Preempt reversed test ray if fwd already outside ROI */
return 0;
} while (rayFlip ^= 1);
/* inROI==0 if odd #crossings (=inside) in each iteration */
return !inROI;
}
/* No ROIs defined; accept photon unconditionally */
return 1;
}

Event Timeline