#include <sys/timeb.h>
#include "gpuCacheSpatialSubdivision.h"
#include <maya/MMatrix.h>
#include <stdlib.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>
#include <maya/MGlobal.h>
#include <set>
namespace GPUCache {
gpuCacheIsectAccelParams
gpuCacheIsectAccelParams::uniformGridParams(
int divX,
int divY,
int divZ
)
{
return gpuCacheIsectAccelParams( gpuCacheIsectAccelParams::kUniformGrid,
divX, divY, divZ );
}
gpuCacheIsectAccelParams
gpuCacheIsectAccelParams::autoUniformGridParams()
{
return gpuCacheIsectAccelParams( gpuCacheIsectAccelParams::kAutoUniformGrid,
-1, -1, -1 );
}
gpuCacheIsectAccelParams::gpuCacheIsectAccelParams()
: fAlgorithm( gpuCacheIsectAccelParams::kUniformGrid ),
fDivX(10),
fDivY(10),
fDivZ(10)
{
}
gpuCacheIsectAccelParams::gpuCacheIsectAccelParams(
int alg,
int divX,
int divY,
int divZ
)
: fAlgorithm(alg),
fDivX(divX),
fDivY(divY),
fDivZ(divZ)
{
}
int gpuCacheIsectAccelParams::operator==( const gpuCacheIsectAccelParams& rhs )
{
if( (fAlgorithm == rhs.fAlgorithm) &&
(fDivX == rhs.fDivX) &&
(fDivY == rhs.fDivY) &&
(fDivZ == rhs.fDivZ) )
{
return 1;
}
else
{
return 0;
}
}
int gpuCacheIsectAccelParams::operator!=( const gpuCacheIsectAccelParams& rhs )
{
return !((*this)==rhs);
}
class gpuCacheVoxelGrid : public SpatialGrid {
public:
typedef SpatialGrid ParentClass;
const unsigned int numTriangles;
const index_t* srcTriangleVertIndices;
const float* srcPositions;
gridPoint3<int>* indexArrayRange;
gpuCacheVoxelGrid(
const MBoundingBox &bound,
const gridPoint3<int> &numVoxels,
unsigned int thisNumTriangles,
const index_t* thisSrcTriangleVertIndices,
const float* thisSrcPositions):
SpatialGrid( bound, numVoxels ),
numTriangles(thisNumTriangles),
srcTriangleVertIndices(thisSrcTriangleVertIndices),
srcPositions(thisSrcPositions)
{
addTrianglesToGrid();
}
~gpuCacheVoxelGrid() override;
void operator()( const tbb::blocked_range<unsigned int> &br ) const;
void getTris(
MIntArray &triArray,
const gridPoint3<int> &grid);
float getMemoryFootprint() override;
private:
void addTrianglesToGrid();
};
gpuCacheVoxelGrid::~gpuCacheVoxelGrid()
{
}
struct TbbBuildVoxelGrid {
const gpuCacheVoxelGrid *gpuGrid;
void operator()( const tbb::blocked_range<unsigned int>& br ) const {
for (unsigned int j = br.begin(); j != br.end(); j++) {
index_t idx0=gpuGrid->srcTriangleVertIndices[3*j]*3;
index_t idx1=gpuGrid->srcTriangleVertIndices[3*j+1]*3;
index_t idx2=gpuGrid->srcTriangleVertIndices[3*j+2]*3;
MPoint vertex1(gpuGrid->srcPositions[idx0],gpuGrid->srcPositions[idx0+1],gpuGrid->srcPositions[idx0+2]);
MPoint vertex2(gpuGrid->srcPositions[idx1],gpuGrid->srcPositions[idx1+1],gpuGrid->srcPositions[idx1+2]);
MPoint vertex3(gpuGrid->srcPositions[idx2],gpuGrid->srcPositions[idx2+1],gpuGrid->srcPositions[idx2+2]);
gpuGrid->getVoxelRange( bbox2, gpuGrid->indexArrayRange[j*2], gpuGrid->indexArrayRange[j*2+1] );
}
}
TbbBuildVoxelGrid( const gpuCacheVoxelGrid *thisGpuGrid ) : gpuGrid(thisGpuGrid) {}
TbbBuildVoxelGrid( const TbbBuildVoxelGrid &thisTbbVoxelGrid ) : gpuGrid(thisTbbVoxelGrid.gpuGrid) {}
~TbbBuildVoxelGrid() {}
};
void gpuCacheVoxelGrid::addTrianglesToGrid() {
indexArrayRange = new gridPoint3<int>[2*numTriangles];
TbbBuildVoxelGrid tbbBVG(this);
tbb::parallel_for(tbb::blocked_range<unsigned int>(0, numTriangles, 100), tbbBVG, tbb::auto_partitioner());
for (unsigned int j = 0; j < numTriangles; j++) {
const gridPoint3<int>& minIndices = indexArrayRange[j*2];
const gridPoint3<int>& maxIndices = indexArrayRange[j*2+1];
for( int x = minIndices[0]; x <= maxIndices[0]; x++ ) {
for( int y = minIndices[1]; y <= maxIndices[1]; y++ ) {
for( int z = minIndices[2]; z <= maxIndices[2]; z++ ) {
MUintArray *indices = getVoxelContents( gridPoint3<int>(x,y,z) );
}
}
}
}
delete [] indexArrayRange;
}
void gpuCacheVoxelGrid::getTris(
MIntArray &triArray,
const gridPoint3<int> &gridLocation)
{
MUintArray *values = getVoxelContents( gridLocation );
unsigned int numTriangles = values->
length();
if(triArray.
length() < numTriangles){
}
unsigned int nAdded = 0;
for( unsigned int i = 0; i < numTriangles; i++ ) {
unsigned int index = (*values)[i];
triArray[nAdded] = index;
nAdded++;
}
if(triArray.
length() > nAdded){
}
}
float
gpuCacheVoxelGrid::getMemoryFootprint()
{
float totalClassSize = ParentClass::getMemoryFootprint();
return totalClassSize;
}
class SimpleTimer
{
public:
SimpleTimer() {};
void startTimer()
{
fStartTime = GetMilliCount();
}
double elapsedTime()
{
return GetMilliSpan();
}
private:
int GetMilliCount()
{
timeb tb;
ftime( &tb );
int nCount = tb.millitm + (tb.time & 0xfffff) * 1000;
return nCount;
}
int GetMilliSpan()
{
int nSpan = GetMilliCount() - fStartTime;
if ( nSpan < 0 )
nSpan += 0x100000 * 1000;
return nSpan;
}
int fStartTime;
};
int gpuCacheSpatialSubdivision::fsTotalNumActiveSpatialSubdivisions = 0;
int gpuCacheSpatialSubdivision::fsTotalNumCreatedSpatialSubdivisions = 0;
float gpuCacheSpatialSubdivision::fsTotalMemoryFootprint = 0.0;
float gpuCacheSpatialSubdivision::fsPeakMemoryFootprint = 0.0;
float gpuCacheSpatialSubdivision::fsTotalBuildTime = 0.0;
gridPoint3<int>
computeBoundsFromTriangleDensity(
unsigned int numTriangles, const index_t* srcTriangleVertIndices, const float* srcPositions,
int trianglesPerVoxel,
const gridPoint3<int>& minVoxels,
const gridPoint3<int>& maxVoxels
)
{
gridPoint3<int> res;
float trianglesAlongAxis = powf( float(trianglesPerVoxel), 0.33f );
float totalSize[3] = { 0.0, 0.0, 0.0 };
for (unsigned int j = 0; j < numTriangles; j++) {
index_t idx0=srcTriangleVertIndices[3*j]*3;
index_t idx1=srcTriangleVertIndices[3*j+1]*3;
index_t idx2=srcTriangleVertIndices[3*j+2]*3;
MPoint vertex1(srcPositions[idx0],srcPositions[idx0+1],srcPositions[idx0+2]);
MPoint vertex2(srcPositions[idx1],srcPositions[idx1+1],srcPositions[idx1+2]);
MPoint vertex3(srcPositions[idx2],srcPositions[idx2+1],srcPositions[idx2+2]);
totalSize[0] += triBound.
width();
totalSize[1] += triBound.
height();
totalSize[2] += triBound.
depth();
}
float boundSize[3] = {
};
for( int i = 0; i < 3; i++ )
{
float avgSize = totalSize[i] / numTriangles;
float voxelSize = avgSize * trianglesAlongAxis;
float numVoxels = boundSize[i] / voxelSize;
int iNumVoxels;
if( numVoxels < minVoxels[i] )
{
iNumVoxels = minVoxels[i];
}
else if( numVoxels > maxVoxels[i] )
{
iNumVoxels = maxVoxels[i];
}
else
{
iNumVoxels = (int)ceil(numVoxels);
}
res[i] = iNumVoxels;
}
return res;
}
gpuCacheSpatialSubdivision::gpuCacheSpatialSubdivision(
const unsigned int numTriangles,
const index_t* srcTriangleVertIndices,
const float* srcPositions,
const gpuCacheIsectAccelParams& accelParams
)
: fAccelParams(accelParams)
{
SimpleTimer myTimer;
myTimer.startTimer();
if( (accelParams.fAlgorithm == gpuCacheIsectAccelParams::kUniformGrid) ||
(accelParams.fAlgorithm == gpuCacheIsectAccelParams::kAutoUniformGrid) )
{
gridPoint3<int> numSub;
if( fAccelParams.fAlgorithm == gpuCacheIsectAccelParams::kAutoUniformGrid )
{
numSub = computeBoundsFromTriangleDensity( numTriangles, srcTriangleVertIndices, srcPositions,
bounds,
12,
gridPoint3<int>(1,1,1),
gridPoint3<int>(100,100,100) );
}
else
{
numSub = gridPoint3<int>( fAccelParams.fDivX,
fAccelParams.fDivY,
fAccelParams.fDivZ );
}
fVoxelGrid = new gpuCacheVoxelGrid( bounds, numSub, numTriangles, srcTriangleVertIndices, srcPositions);
}
fMemoryFootprint = fVoxelGrid->getMemoryFootprint();
fBuildTime = (float)myTimer.elapsedTime();
fsTotalMemoryFootprint += fMemoryFootprint;
if( fsTotalMemoryFootprint > fsPeakMemoryFootprint )
{
fsPeakMemoryFootprint = fsTotalMemoryFootprint;
}
fsTotalBuildTime += fBuildTime;
fsTotalNumActiveSpatialSubdivisions++;
fsTotalNumCreatedSpatialSubdivisions++;
}
gpuCacheSpatialSubdivision::~gpuCacheSpatialSubdivision()
{
deleteVoxelGrid();
}
void gpuCacheSpatialSubdivision::deleteVoxelGrid()
{
if( fVoxelGrid != NULL )
{
fsTotalNumActiveSpatialSubdivisions--;
fsTotalMemoryFootprint -= fMemoryFootprint;
delete fVoxelGrid;
fVoxelGrid = NULL;
}
}
struct TbbFindClosestEdgePoint {
double minDist;
const index_t* srcTriangleVertIndices;
const float* srcPositions;
void reset() {
minDist = std::numeric_limits<double>::max();
}
TbbFindClosestEdgePoint(
const index_t * thisSrcTriangleVertIndices,
const float *thisSrcPositions,
const MPoint &thisRayPoint,
const MVector &thisRayDirection,
const MIntArray &thisTriArray) :
srcTriangleVertIndices(thisSrcTriangleVertIndices), srcPositions(thisSrcPositions), rayPoint(thisRayPoint), rayDirection(thisRayDirection), triArray(thisTriArray) {
reset();
}
TbbFindClosestEdgePoint(const TbbFindClosestEdgePoint& fCEP, tbb::split) :
srcTriangleVertIndices(fCEP.srcTriangleVertIndices), srcPositions(fCEP.srcPositions), rayPoint(fCEP.rayPoint), rayDirection(fCEP.rayDirection), triArray(fCEP.triArray) {
reset();
}
void operator()(tbb::blocked_range<size_t> r) {
size_t end=r.end();
for( size_t j=r.begin(); j!=end; ++j ) {
int triIndex = triArray[j];
index_t idx0=srcTriangleVertIndices[3*triIndex]*3;
index_t idx1=srcTriangleVertIndices[3*triIndex+1]*3;
index_t idx2=srcTriangleVertIndices[3*triIndex+2]*3;
MPoint vertex1(srcPositions[idx0],srcPositions[idx0+1],srcPositions[idx0+2]);
MPoint vertex2(srcPositions[idx1],srcPositions[idx1+1],srcPositions[idx1+2]);
MPoint vertex3(srcPositions[idx2],srcPositions[idx2+1],srcPositions[idx2+2]);
double dist = gpuCacheIsectUtil::getEdgeSnapPointOnTriangle(rayPoint,rayDirection,vertex1,vertex2,vertex3,clsPoint);
if(dist<minDist){
minDist = dist;
closestPoint = clsPoint;
}
}
}
void join( TbbFindClosestEdgePoint &other ) {
if(other.minDist < minDist ) {
minDist = other.minDist;
closestPoint = other.closestPoint;
}
}
};
double gpuCacheSpatialSubdivision::getEdgeSnapPoint(const unsigned int numTriangles,
const index_t* srcTriangleVertIndices,
const float* srcPositions,
{
TbbFindClosestEdgePoint fCP( srcTriangleVertIndices, srcPositions, rayPoint, rayDirection, triArray );
tbb::parallel_reduce(tbb::blocked_range<size_t>(0, triArray.
length()), fCP );
closestPoint = fCP.closestPoint;
return fCP.minDist;
}
double gpuCacheSpatialSubdivision::getEdgeSnapPoint(const unsigned int numTriangles,
const index_t* srcTriangleVertIndices,
const float* srcPositions,
{
std::set< gridPoint3<int> > potentialVoxels;
gridPoint3<int> numVoxelsByAxis = fVoxelGrid->getNumVoxels();
int numVoxels = numVoxelsByAxis[0] * numVoxelsByAxis[1] * numVoxelsByAxis[2];
MPoint voxSizes(bbox.
width()/numVoxelsByAxis[0],bbox.
height()/numVoxelsByAxis[1],bbox.
depth()/numVoxelsByAxis[2]);
MPoint expandAmount = 0.1*voxSizes;
double minDist = std::numeric_limits<double>::max();
bool *checkedBox = new bool[numVoxels];
double *allDists = new double[numVoxels];
gridPoint3<int> closestGridPoint;
for (int i=0;i<numVoxelsByAxis[0];i++) {
for (int j=0;j<numVoxelsByAxis[1];j++) {
for (int k=0;k<numVoxelsByAxis[2];k++) {
gridPoint3<int> gridLocation = gridPoint3<int>(i,j,k);
MUintArray *values = fVoxelGrid->getVoxelContents( gridLocation );
int linearIndex = k * (numVoxelsByAxis[0] * numVoxelsByAxis[1]) + j * numVoxelsByAxis[0] + i;
checkedBox[linearIndex] = false;
if(values->length()>0){
MPoint c1 = bbox.
min() +
MPoint(i*voxSizes[0],j*voxSizes[1],k*voxSizes[2]);
allDists[linearIndex] = gpuCacheIsectUtil::getEdgeSnapPointOnBox(rayPoint,rayDirection,voxBox,queryPoint);
if(allDists[linearIndex] < minDist){
minDist = allDists[linearIndex];
closestGridPoint = gridLocation;
}
}
else {
allDists[linearIndex] = std::numeric_limits<double>::max();
}
}
}
}
for (int i=0;i<numVoxelsByAxis[0];i++) {
for (int j=0;j<numVoxelsByAxis[1];j++) {
for (int k=0;k<numVoxelsByAxis[2];k++) {
int linearIndex = k * (numVoxelsByAxis[0] * numVoxelsByAxis[1]) + j * numVoxelsByAxis[0] + i;
if(allDists[linearIndex]<=minDist){
potentialVoxels.insert(gridPoint3<int>(i,j,k));
checkedBox[linearIndex]=true;
}
}
}
}
minDist = std::numeric_limits<double>::max();
while(potentialVoxels.size()>0){
std::set< gridPoint3<int> >::iterator voxelIt = potentialVoxels.begin();
gridPoint3<int> gridLoc = *voxelIt;
potentialVoxels.erase(voxelIt);
int linearIndex = gridLoc[2] * (numVoxelsByAxis[0] * numVoxelsByAxis[1]) + gridLoc[1] * numVoxelsByAxis[0] + gridLoc[0];
if(allDists[linearIndex]>minDist) continue;
fVoxelGrid->getTris( triArray, gridLoc );
double dist = getEdgeSnapPoint(numTriangles,srcTriangleVertIndices,srcPositions,rayPoint, rayDirection,triArray,clsPoint);
if(dist<minDist){
minDist = dist;
closestPoint = clsPoint;
for (int i=0;i<numVoxelsByAxis[0];i++){
for (int j=0;j<numVoxelsByAxis[1];j++){
for (int k=0;k<numVoxelsByAxis[2];k++) {
int linearIndex = k * (numVoxelsByAxis[0] * numVoxelsByAxis[1]) + j * numVoxelsByAxis[0] + i;
if(!checkedBox[linearIndex] && allDists[linearIndex]<=minDist){
potentialVoxels.insert(gridPoint3<int>(i,j,k));
checkedBox[linearIndex]=true;
}
}
}
}
}
}
delete[] checkedBox;
delete[] allDists;
return minDist;
}
struct TbbFindClosestPoint {
bool foundPoint;
double minDist;
const index_t *srcTriangleVertIndices;
const float *srcPositions;
void reset() {
foundPoint = false;
minDist = std::numeric_limits<double>::max();
}
TbbFindClosestPoint(
const index_t * thisSrcTriangleVertIndices,
const float *thisSrcPositions,
const MIntArray &thisTriArray,
const MPoint &thisQueryPoint ) :
srcTriangleVertIndices(thisSrcTriangleVertIndices), srcPositions(thisSrcPositions), triArray(thisTriArray), queryPoint(thisQueryPoint) {
reset();
}
TbbFindClosestPoint(const TbbFindClosestPoint& fCP, tbb::split) :
srcTriangleVertIndices(fCP.srcTriangleVertIndices), srcPositions(fCP.srcPositions), triArray(fCP.triArray), queryPoint(fCP.queryPoint) {
reset();
}
void operator()(tbb::blocked_range<size_t> r) {
int end=r.end();
for( int j=r.begin(); j!=end; ++j ) {
int triIndex = triArray[j];
index_t idx0=srcTriangleVertIndices[3*triIndex]*3;
index_t idx1=srcTriangleVertIndices[3*triIndex+1]*3;
index_t idx2=srcTriangleVertIndices[3*triIndex+2]*3;
MPoint vertex1(srcPositions[idx0],srcPositions[idx0+1],srcPositions[idx0+2]);
MPoint vertex2(srcPositions[idx1],srcPositions[idx1+1],srcPositions[idx1+2]);
MPoint vertex3(srcPositions[idx2],srcPositions[idx2+1],srcPositions[idx2+2]);
if(gpuCacheIsectUtil::getClosestPointOnTri(queryPoint, vertex1, vertex2, vertex3, clsPoint, minDist)){
closestPoint = clsPoint;
foundPoint = true;
}
}
}
void join( TbbFindClosestPoint &other ) {
if( other.foundPoint && other.minDist < minDist ) {
foundPoint = true;
minDist = other.minDist;
closestPoint = other.closestPoint;
}
}
};
bool gpuCacheSpatialSubdivision::closestPointToPoint(const unsigned int numTriangles,
const index_t* srcTriangleVertIndices,
const float* srcPositions,
{
TbbFindClosestPoint fCP( srcTriangleVertIndices, srcPositions, triArray, queryPoint );
tbb::parallel_reduce(tbb::blocked_range<size_t>(0, triArray.
length()), fCP );
if( fCP.foundPoint ) {
closestPoint = fCP.closestPoint;
return true;
}
return false;
}
void gpuCacheSpatialSubdivision::closestPointToPoint(const unsigned int numTriangles,
const index_t* srcTriangleVertIndices,
const float* srcPositions,
{
double minDist = std::numeric_limits<double>::max();
std::set< gridPoint3<int> > potentialVoxels;
std::set< gridPoint3<int> > checkedVoxels;
gridPoint3<int> gridLocOrg;
fVoxelGrid->getClosestVoxelCoords(queryPoint,gridLocOrg);
potentialVoxels.insert(gridLocOrg);
bool foundPoint = false;
int expandVox = 0;
while (!foundPoint)
{
while(potentialVoxels.size()>0){
std::set< gridPoint3<int> >::iterator voxelIt = potentialVoxels.begin();
gridPoint3<int> gridLoc = *voxelIt;
fVoxelGrid->getTris( triArray, gridLoc );
checkedVoxels.
insert(gridLoc);
potentialVoxels.erase(voxelIt);
if(closestPointToPoint(numTriangles,srcTriangleVertIndices,srcPositions,queryPoint,triArray,clsPoint)){
if(dist<minDist){
minDist = dist;
closestPoint = clsPoint;
foundPoint = true;
gridPoint3<int> gridLocMin;
gridPoint3<int> gridLocMax;
fVoxelGrid->getClosestVoxelCoords(
MPoint(queryPoint[0] - dist, queryPoint[1] - dist, queryPoint[2] - dist),gridLocMin);
fVoxelGrid->getClosestVoxelCoords(
MPoint(queryPoint[0] + dist, queryPoint[1] + dist, queryPoint[2] + dist),gridLocMax);
for(int i=gridLocMin[0]; i<=gridLocMax[0]; i++) {
for(int j=gridLocMin[1]; j<=gridLocMax[1]; j++) {
for(int k=gridLocMin[2]; k<=gridLocMax[2]; k++) {
gridPoint3<int> gridLocNew = gridPoint3<int>(i,j,k);
if(fVoxelGrid->isValidVoxel(gridLocNew) && checkedVoxels.find(gridLocNew) == checkedVoxels.end()) {
potentialVoxels.insert(gridLocNew);
}
}
}
}
}
}
}
expandVox++;
if(!foundPoint){
for(int i=-expandVox; i<=expandVox; i++) {
for(int j=-expandVox; j<=expandVox; j++) {
for(int k=-expandVox; k<=expandVox; k++) {
gridPoint3<int> gridLocNew = gridLocOrg + gridPoint3<int>(i,j,k);
if(fVoxelGrid->isValidVoxel(gridLocNew) && checkedVoxels.find(gridLocNew) == checkedVoxels.end()) {
potentialVoxels.insert(gridLocNew);
}
}
}
}
}
}
}
struct TbbFindClosestIntersection {
bool foundIntersection;
double minDist;
const index_t *srcTriangleVertIndices;
const float *srcPositions;
void reset() {
foundIntersection = false;
minDist = std::numeric_limits<double>::max();
}
TbbFindClosestIntersection(
const index_t * thisSrcTriangleVertIndices,
const float *thisSrcPositions,
const MIntArray &thisTriArray,
const MPoint &thisRaySource,
const MVector &thisRayDirection ) :
srcTriangleVertIndices(thisSrcTriangleVertIndices), srcPositions(thisSrcPositions), triArray(thisTriArray), raySource(thisRaySource), rayDirection(thisRayDirection) {
reset();
}
TbbFindClosestIntersection(const TbbFindClosestIntersection& fCIS, tbb::split) :
srcTriangleVertIndices(fCIS.srcTriangleVertIndices), srcPositions(fCIS.srcPositions), triArray(fCIS.triArray), raySource(fCIS.raySource), rayDirection(fCIS.rayDirection) {
reset();
}
void operator()(tbb::blocked_range<size_t> r) {
int end=r.end();
for( int i=r.begin(); i!=end; ++i ) {
int triIndex = triArray[i];
index_t idx0=srcTriangleVertIndices[3*triIndex]*3;
index_t idx1=srcTriangleVertIndices[3*triIndex+1]*3;
index_t idx2=srcTriangleVertIndices[3*triIndex+2]*3;
MPoint vertex1(srcPositions[idx0],srcPositions[idx0+1],srcPositions[idx0+2]);
MPoint vertex2(srcPositions[idx1],srcPositions[idx1+1],srcPositions[idx1+2]);
MPoint vertex3(srcPositions[idx2],srcPositions[idx2+1],srcPositions[idx2+2]);
MVector c0, c1, rhs, crossc1c2, crossc0rhs;
double beta, gamm, t, M;
c0 = vertex1 - vertex2;
c1 = vertex1 - vertex3;
rhs = vertex1 -
MVector(raySource);
crossc1c2 = c1 ^ rayDirection;
crossc0rhs = c0 ^ rhs;
M = c0 * crossc1c2;
if (M==0) continue;
t = -(c1 * crossc0rhs)/M;
if (t < 0.0 || t > minDist) continue;
beta = (rhs * crossc1c2)/M;
if (beta < 0 || beta > 1) continue;
gamm = (rayDirection * crossc0rhs)/M;
if (gamm < 0 || gamm > 1 - beta) continue;
minDist = t;
closestIntersection = raySource + t * rayDirection;
closestNormal = (c0 ^ c1).normal();
foundIntersection = true;
}
}
void join( TbbFindClosestIntersection &other ) {
if( other.foundIntersection && other.minDist < minDist ) {
foundIntersection = true;
minDist = other.minDist;
closestIntersection = other.closestIntersection;
closestNormal = other.closestNormal;
}
}
};
MStatus gpuCacheSpatialSubdivision::closestIntersection(
const unsigned int numTriangles,
const index_t* srcTriangleVertIndices,
const float* srcPositions,
float maxParam,
)
{
TbbFindClosestIntersection fCIS( srcTriangleVertIndices, srcPositions, triArray, origin, direction );
tbb::parallel_reduce(tbb::blocked_range<size_t>(0, triArray.
length()), fCIS );
if( fCIS.foundIntersection ) {
closestIsect = fCIS.closestIntersection;
isectNormal = fCIS.closestNormal;
}
}
MStatus gpuCacheSpatialSubdivision::closestIntersection(
const unsigned int numTriangles,
const index_t* srcTriangleVertIndices,
const float* srcPositions,
float maxParam,
)
{
SpatialGridWalker it = fVoxelGrid->getRayIterator( origin, direction );
maxParam = fabs(maxParam);
while( !it.isDone() )
{
if( it.curVoxelStartRayParam() > maxParam )
{
break;
}
gridPoint3<int> gridLoc = it.gridLocation();
fVoxelGrid->getTris( triArray, gridLoc);
if ( triArray.
length() > 0 ) {
float voxelMaxParam = std::min( it.curVoxelEndRayParam(), maxParam );
if(
MStatus::kSuccess == closestIntersection( numTriangles, srcTriangleVertIndices, srcPositions, origin, direction,
triArray, voxelMaxParam, closestIsect, isectNormal ) )
{
}
}
it.next();
}
}
float gpuCacheSpatialSubdivision::getMemoryFootprint()
{
return fMemoryFootprint;
}
float gpuCacheSpatialSubdivision::getBuildTime()
{
return fBuildTime;
}
MString gpuCacheSpatialSubdivision::getDescription(
bool includeStats )
{
gridPoint3<int> numVoxels = fVoxelGrid->getNumVoxels();
char buf[512];
if( fAccelParams.fAlgorithm == gpuCacheIsectAccelParams::kUniformGrid )
{
sprintf( buf, "%dx%dx%d Uniform Grid", numVoxels[0],
numVoxels[1],
numVoxels[2] );
}
else if( fAccelParams.fAlgorithm == gpuCacheIsectAccelParams::kAutoUniformGrid )
{
sprintf( buf, "%dx%dx%d Auto-Configured Uniform Grid",
numVoxels[0], numVoxels[1], numVoxels[2] );
}
if( includeStats )
{
char buf2[512];
sprintf( buf2, "build time %.2fs", fBuildTime );
sprintf( buf2, "memory footprint %.2fKB", fMemoryFootprint );
}
return resultStr;
}
MString gpuCacheSpatialSubdivision::systemStats()
{
char buf[1024];
sprintf( buf, "total %d isect accelerators created (%d currently active - "
"total current memory = %.2f KB), total build time = %f ms, "
"peak memory = %.2f KB\n",
fsTotalNumCreatedSpatialSubdivisions,
fsTotalNumActiveSpatialSubdivisions,
fsTotalMemoryFootprint,
fsTotalBuildTime,
fsPeakMemoryFootprint );
}
void gpuCacheSpatialSubdivision::resetSystemStats()
{
fsTotalNumCreatedSpatialSubdivisions = 0;
fsTotalBuildTime = 0.0f;
fsPeakMemoryFootprint = 0.0f;
}
bool
gpuCacheSpatialSubdivision::matchesParams(
const gpuCacheIsectAccelParams& accelParams
)
{
if( fVoxelGrid != NULL )
{
return (fAccelParams == accelParams) ? true : false;
}
else
{
return false;
}
}
}