#include "gpuCacheSpatialGrid.h" 
#include "gpuCacheSpatialGridWalker.h" 
#include <maya/MIntArray.h> 
#include "gpuCacheIsectUtil.h"
SpatialGridWalker::SpatialGridWalker( 
    SpatialGrid *grid )
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    :
fVoxelGrid(grid),
    fOrigin(origin),
    fDirection(direction),
    fDone(false)
{ 
    
    
    if( !grid->bounds().contains( origin ) )
    {
        if(GPUCache::gpuCacheIsectUtil::firstRayIntersection((grid->bounds().min()), (grid->bounds().max()), origin, direction, NULL, &boxIntersectionPt))
        {
            
            
            
            fOrigin = 
MPoint( boxIntersectionPt.
x, 
            float dist = (float) boxIntersectionPt.
distanceTo( origin );
 
            float length = (float) direction.
length();
 
            fCurVoxelStartRayParam = dist/ length;
            fDone = false;
        }
        else
        {
            
            
            
            fDone = true;
            return;
        }
    }
    else
    {
        fCurVoxelStartRayParam = 0;
    }
    fNextAxis = 0;
    fCurDistances = gridPoint3<float>( 1.0e8, 1.0e8, 1.0e8 );
    
    
    
    grid->getVoxelCoords( fOrigin, fCurVoxelCoords, &residual );
    
    
    
    
    
    for( int axis = 0; axis < 3; axis++ )
    {
        
        
        
        
        if( fDirection[axis] > 0 )
        {
            fCurDistances[axis] = (grid->fVoxelSizes[axis]-
                residual[axis])/fDirection[axis];
        }
        else if( fDirection[axis] < 0 )
        {
            fCurDistances[axis] = -(residual[axis]/fDirection[axis]);
        }
        else
        {
            
            
            
            
            
            fCurDistances[axis] = 1.0e8;
        }
        
        
        if( fCurDistances[axis] < fCurDistances[fNextAxis] )
        {
            fNextAxis = axis;
        }
    }
    
    
    
    fCurVoxelEndRayParam = fCurVoxelStartRayParam + fCurDistances[fNextAxis];
}
void SpatialGridWalker::next()
    
    
    
    
    
    
    
    
    
    
    
    
    
{
    
    
    
    
    int curAxis = fNextAxis;
    int otherAxis1 = (curAxis+1)%3;
    int otherAxis2 = (curAxis+2)%3;
    
    
    
    
    if( fDirection[curAxis] >= 0.0 )
    {
        fCurVoxelCoords[curAxis] += 1;
        if( fCurVoxelCoords[curAxis] >= fVoxelGrid->fNumVoxels[curAxis] )
        {
            fDone = true;
        }
    }
    else
    {
        fCurVoxelCoords[curAxis] -= 1;
        if( fCurVoxelCoords[curAxis] < 0 )
        {
            fDone = true;
        }
    }
    fCurVoxelStartRayParam += fCurDistances[curAxis];
    
    
    
    
    
    fCurDistances[otherAxis1] -= fCurDistances[curAxis];
    fCurDistances[otherAxis2] -= fCurDistances[curAxis];
    
    
    
    
    
    fCurDistances[curAxis] = fVoxelGrid->fVoxelSizes[curAxis] / 
        fabs(fDirection[curAxis]);
    
    
    
    if( fCurDistances[otherAxis1] < fCurDistances[otherAxis2] )
    {
        if( fCurDistances[otherAxis1] < fCurDistances[fNextAxis] )
        {
            fNextAxis = otherAxis1;
        }
    }
    else
    {
        if( fCurDistances[otherAxis2] < fCurDistances[fNextAxis] )
        {
            fNextAxis = otherAxis2;
        }
    }
    
    
    fCurVoxelEndRayParam = fCurVoxelStartRayParam + fCurDistances[fNextAxis];
}
bool SpatialGridWalker::isDone()
    
    
    
    
    
    
{
    return fDone;
}
float SpatialGridWalker::curVoxelStartRayParam()
    
    
    
    
    
    
    
{
    return fCurVoxelStartRayParam;
}
float SpatialGridWalker::curVoxelEndRayParam()
    
    
    
    
    
    
{
    return fCurVoxelEndRayParam;
}
    
    
    
    
    
    
    
{
    return fVoxelGrid->getVoxelContents( fCurVoxelCoords );
}
gridPoint3<int> 
    SpatialGridWalker::gridLocation()
    
    
    
    
{
    return fCurVoxelCoords; 
}