Made raycasting, ambient occlusion, and A* pathfinding independant of volume type.

This commit is contained in:
David Williams 2011-05-01 17:26:12 +01:00
parent 27968973a4
commit 6a38d9fca7
8 changed files with 68 additions and 66 deletions

View File

@ -43,8 +43,8 @@ namespace PolyVox
/// This function provides the default method for checking whether a given voxel /// This function provides the default method for checking whether a given voxel
/// is vaid for the path computed by the AStarPathfinder. /// is vaid for the path computed by the AStarPathfinder.
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
bool aStarDefaultVoxelValidator(const LargeVolume<VoxelType>* volData, const Vector3DInt32& v3dPos); bool aStarDefaultVoxelValidator(const VolumeType<VoxelType>* volData, const Vector3DInt32& v3dPos);
/// Provides a configuration for the AStarPathfinder. /// Provides a configuration for the AStarPathfinder.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -57,20 +57,20 @@ namespace PolyVox
/// ///
/// \sa AStarPathfinder /// \sa AStarPathfinder
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
struct AStarPathfinderParams struct AStarPathfinderParams
{ {
public: public:
AStarPathfinderParams AStarPathfinderParams
( (
LargeVolume<VoxelType>* volData, VolumeType<VoxelType>* volData,
const Vector3DInt32& v3dStart, const Vector3DInt32& v3dStart,
const Vector3DInt32& v3dEnd, const Vector3DInt32& v3dEnd,
std::list<Vector3DInt32>* listResult, std::list<Vector3DInt32>* listResult,
float fHBias = 1.0, float fHBias = 1.0,
uint32_t uMaxNoOfNodes = 10000, uint32_t uMaxNoOfNodes = 10000,
Connectivity connectivity = TwentySixConnected, Connectivity connectivity = TwentySixConnected,
polyvox_function<bool (const LargeVolume<VoxelType>*, const Vector3DInt32&)> funcIsVoxelValidForPath = &aStarDefaultVoxelValidator<VoxelType>, polyvox_function<bool (const VolumeType<VoxelType>*, const Vector3DInt32&)> funcIsVoxelValidForPath = &aStarDefaultVoxelValidator<VolumeType, VoxelType>,
polyvox_function<void (float)> funcProgressCallback = 0 polyvox_function<void (float)> funcProgressCallback = 0
) )
:volume(volData) :volume(volData)
@ -86,7 +86,7 @@ namespace PolyVox
} }
/// This is the volume through which the AStarPathfinder must find a path. /// This is the volume through which the AStarPathfinder must find a path.
LargeVolume<VoxelType>* volume; VolumeType<VoxelType>* volume;
/// The start point for the pathfinding algorithm. /// The start point for the pathfinding algorithm.
Vector3DInt32 start; Vector3DInt32 start;
@ -125,7 +125,7 @@ namespace PolyVox
/// you could check to ensure that the voxel above is empty and the voxel below is solid. /// you could check to ensure that the voxel above is empty and the voxel below is solid.
/// ///
/// \sa aStarDefaultVoxelValidator /// \sa aStarDefaultVoxelValidator
polyvox_function<bool (const LargeVolume<VoxelType>*, const Vector3DInt32&)> isVoxelValidForPath; polyvox_function<bool (const VolumeType<VoxelType>*, const Vector3DInt32&)> isVoxelValidForPath;
/// This function is called by the AStarPathfinder to report on its progress in getting to /// This function is called by the AStarPathfinder to report on its progress in getting to
/// the goal. The progress is reported by computing the distance from the closest node found /// the goal. The progress is reported by computing the distance from the closest node found
@ -159,11 +159,11 @@ namespace PolyVox
/// ///
/// \sa AStarPathfinderParams /// \sa AStarPathfinderParams
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
class AStarPathfinder class AStarPathfinder
{ {
public: public:
AStarPathfinder(const AStarPathfinderParams<VoxelType>& params); AStarPathfinder(const AStarPathfinderParams<VolumeType, VoxelType>& params);
void execute(); void execute();
@ -185,7 +185,7 @@ namespace PolyVox
float m_fProgress; float m_fProgress;
AStarPathfinderParams<VoxelType> m_params; AStarPathfinderParams<VolumeType, VoxelType> m_params;
}; };
} }

View File

@ -30,8 +30,8 @@ namespace PolyVox
/// volume and if its density is below that returned by the voxel's getDensity() function. /// volume and if its density is below that returned by the voxel's getDensity() function.
/// \return true is the voxel is valid for the path /// \return true is the voxel is valid for the path
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
bool aStarDefaultVoxelValidator(const LargeVolume<VoxelType>* volData, const Vector3DInt32& v3dPos) bool aStarDefaultVoxelValidator(const VolumeType<VoxelType>* volData, const Vector3DInt32& v3dPos)
{ {
//Voxels are considered valid candidates for the path if they are inside the volume... //Voxels are considered valid candidates for the path if they are inside the volume...
if(volData->getEnclosingRegion().containsPoint(v3dPos) == false) if(volData->getEnclosingRegion().containsPoint(v3dPos) == false)
@ -52,14 +52,14 @@ namespace PolyVox
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// AStarPathfinder Class // AStarPathfinder Class
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
AStarPathfinder<VoxelType>::AStarPathfinder(const AStarPathfinderParams<VoxelType>& params) AStarPathfinder<VolumeType, VoxelType>::AStarPathfinder(const AStarPathfinderParams<VolumeType, VoxelType>& params)
:m_params(params) :m_params(params)
{ {
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void AStarPathfinder<VoxelType>::execute() void AStarPathfinder<VolumeType, VoxelType>::execute()
{ {
//Clear any existing nodes //Clear any existing nodes
allNodes.clear(); allNodes.clear();
@ -191,8 +191,8 @@ namespace PolyVox
} }
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void AStarPathfinder<VoxelType>::processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal) void AStarPathfinder<VolumeType, VoxelType>::processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal)
{ {
bool bIsVoxelValidForPath = m_params.isVoxelValidForPath(m_params.volume, neighbourPos); bool bIsVoxelValidForPath = m_params.isVoxelValidForPath(m_params.volume, neighbourPos);
if(!bIsVoxelValidForPath) if(!bIsVoxelValidForPath)
@ -247,8 +247,8 @@ namespace PolyVox
} }
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
float AStarPathfinder<VoxelType>::SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b) float AStarPathfinder<VolumeType, VoxelType>::SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
{ {
//This is the only heuristic I'm sure of - just use the manhatten distance for the 6-connected case. //This is the only heuristic I'm sure of - just use the manhatten distance for the 6-connected case.
uint32_t faceSteps = abs(a.getX()-b.getX()) + abs(a.getY()-b.getY()) + abs(a.getZ()-b.getZ()); uint32_t faceSteps = abs(a.getX()-b.getX()) + abs(a.getY()-b.getY()) + abs(a.getZ()-b.getZ());
@ -256,8 +256,8 @@ namespace PolyVox
return faceSteps * 1.0f; return faceSteps * 1.0f;
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
float AStarPathfinder<VoxelType>::EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b) float AStarPathfinder<VolumeType, VoxelType>::EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
{ {
//I'm not sure of the correct heuristic for the 18-connected case, so I'm just letting it fall through to the //I'm not sure of the correct heuristic for the 18-connected case, so I'm just letting it fall through to the
//6-connected case. This means 'h' will be bigger than it should be, resulting in a faster path which may not //6-connected case. This means 'h' will be bigger than it should be, resulting in a faster path which may not
@ -266,8 +266,8 @@ namespace PolyVox
return SixConnectedCost(a,b); return SixConnectedCost(a,b);
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
float AStarPathfinder<VoxelType>::TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b) float AStarPathfinder<VolumeType, VoxelType>::TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
{ {
//Can't say I'm certain about this heuristic - if anyone has //Can't say I'm certain about this heuristic - if anyone has
//a better idea of what it should be then please let me know. //a better idea of what it should be then please let me know.
@ -288,8 +288,8 @@ namespace PolyVox
return cornerSteps * sqrt_3 + edgeSteps * sqrt_2 + faceSteps * sqrt_1; return cornerSteps * sqrt_3 + edgeSteps * sqrt_2 + faceSteps * sqrt_1;
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
float AStarPathfinder<VoxelType>::computeH(const Vector3DInt32& a, const Vector3DInt32& b) float AStarPathfinder<VolumeType, VoxelType>::computeH(const Vector3DInt32& a, const Vector3DInt32& b)
{ {
float hVal; float hVal;

View File

@ -29,19 +29,19 @@ freely, subject to the following restrictions:
namespace PolyVox namespace PolyVox
{ {
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
class AmbientOcclusionCalculator class AmbientOcclusionCalculator
{ {
public: public:
AmbientOcclusionCalculator(LargeVolume<VoxelType>* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement); AmbientOcclusionCalculator(VolumeType<VoxelType>* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement);
~AmbientOcclusionCalculator(); ~AmbientOcclusionCalculator();
void execute(void); void execute(void);
private: private:
Region m_region; Region m_region;
typename LargeVolume<VoxelType>::Sampler m_sampVolume; typename VolumeType<VoxelType>::Sampler m_sampVolume;
LargeVolume<VoxelType>* m_volInput; VolumeType<VoxelType>* m_volInput;
Array<3, uint8_t>* m_arrayResult; Array<3, uint8_t>* m_arrayResult;
float m_fRayLength; float m_fRayLength;

View File

@ -28,10 +28,12 @@ freely, subject to the following restrictions:
#include "PolyVoxImpl/RandomUnitVectors.h" #include "PolyVoxImpl/RandomUnitVectors.h"
#include "PolyVoxImpl/RandomVectors.h" #include "PolyVoxImpl/RandomVectors.h"
#include <algorithm>
namespace PolyVox namespace PolyVox
{ {
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
AmbientOcclusionCalculator<VoxelType>::AmbientOcclusionCalculator(LargeVolume<VoxelType>* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement) AmbientOcclusionCalculator<VolumeType, VoxelType>::AmbientOcclusionCalculator(VolumeType<VoxelType>* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement)
:m_region(region) :m_region(region)
,m_sampVolume(volInput) ,m_sampVolume(volInput)
,m_volInput(volInput) ,m_volInput(volInput)
@ -54,18 +56,18 @@ namespace PolyVox
mIndexIncreament = 1; mIndexIncreament = 1;
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
AmbientOcclusionCalculator<VoxelType>::~AmbientOcclusionCalculator() AmbientOcclusionCalculator<VolumeType, VoxelType>::~AmbientOcclusionCalculator()
{ {
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void AmbientOcclusionCalculator<VoxelType>::execute(void) void AmbientOcclusionCalculator<VolumeType, VoxelType>::execute(void)
{ {
const int iRatioX = m_volInput->getWidth() / m_arrayResult->getDimension(0); const int iRatioX = m_volInput->getWidth() / m_arrayResult->getDimension(0);
const int iRatioY = m_volInput->getHeight() / m_arrayResult->getDimension(1); const int iRatioY = m_volInput->getHeight() / m_arrayResult->getDimension(1);
const int iRatioZ = m_volInput->getDepth() / m_arrayResult->getDimension(2); const int iRatioZ = m_volInput->getDepth() / m_arrayResult->getDimension(2);
const int iRatioMax = std::max(std::max(iRatioX, iRatioY), iRatioZ); const int iRatioMax = (std::max)((std::max)(iRatioX, iRatioY), iRatioZ);
const float fRatioX = iRatioX; const float fRatioX = iRatioX;
const float fRatioY = iRatioY; const float fRatioY = iRatioY;
@ -82,7 +84,7 @@ namespace PolyVox
const Vector3DFloat v3dOffset(0.5f,0.5f,0.5f); const Vector3DFloat v3dOffset(0.5f,0.5f,0.5f);
RaycastResult raycastResult; RaycastResult raycastResult;
Raycast<VoxelType> raycast(m_volInput, Vector3DFloat(0.0f,0.0f,0.0f), Vector3DFloat(1.0f,1.0f,1.0f), raycastResult); Raycast<VolumeType, VoxelType> raycast(m_volInput, Vector3DFloat(0.0f,0.0f,0.0f), Vector3DFloat(1.0f,1.0f,1.0f), raycastResult);
//This loop iterates over the bottom-lower-left voxel in each of the cells in the output array //This loop iterates over the bottom-lower-left voxel in each of the cells in the output array
for(uint16_t z = m_region.getLowerCorner().getZ(); z <= m_region.getUpperCorner().getZ(); z += iRatioZ) for(uint16_t z = m_region.getLowerCorner().getZ(); z <= m_region.getUpperCorner().getZ(); z += iRatioZ)

View File

@ -80,12 +80,12 @@ namespace PolyVox
/// surace extractors. It's behaviour with the Marching Cubes surface extractor has not /// surace extractors. It's behaviour with the Marching Cubes surface extractor has not
/// been tested yet. /// been tested yet.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
class Raycast class Raycast
{ {
public: public:
///Constructor ///Constructor
Raycast(LargeVolume<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, RaycastResult& result); Raycast(VolumeType<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, RaycastResult& result);
///Sets the start position for the ray. ///Sets the start position for the ray.
void setStart(const Vector3DFloat& v3dStart); void setStart(const Vector3DFloat& v3dStart);
@ -100,8 +100,8 @@ namespace PolyVox
void doRaycast(float x1, float y1, float z1, float x2, float y2, float z2); void doRaycast(float x1, float y1, float z1, float x2, float y2, float z2);
LargeVolume<VoxelType>* m_volData; VolumeType<VoxelType>* m_volData;
typename LargeVolume<VoxelType>::Sampler m_sampVolume; typename VolumeType<VoxelType>::Sampler m_sampVolume;
Vector3DFloat m_v3dStart; Vector3DFloat m_v3dStart;
Vector3DFloat m_v3dDirection; Vector3DFloat m_v3dDirection;

View File

@ -30,8 +30,8 @@ namespace PolyVox
/// represents the length of the ray. /// represents the length of the ray.
/// \param result An instance of RaycastResult in which the result will be stored. /// \param result An instance of RaycastResult in which the result will be stored.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
Raycast<VoxelType>::Raycast(LargeVolume<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, RaycastResult& result) Raycast<VolumeType, VoxelType>::Raycast(VolumeType<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, RaycastResult& result)
:m_volData(volData) :m_volData(volData)
,m_sampVolume(volData) ,m_sampVolume(volData)
,m_v3dStart(v3dStart) ,m_v3dStart(v3dStart)
@ -43,8 +43,8 @@ namespace PolyVox
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \param v3dStart The starting position of the ray. /// \param v3dStart The starting position of the ray.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void Raycast<VoxelType>::setStart(const Vector3DFloat& v3dStart) void Raycast<VolumeType, VoxelType>::setStart(const Vector3DFloat& v3dStart)
{ {
m_v3dStart = v3dStart; m_v3dStart = v3dStart;
} }
@ -53,8 +53,8 @@ namespace PolyVox
/// \param v3dDirection The direction of the ray. The length of this vector also /// \param v3dDirection The direction of the ray. The length of this vector also
/// represents the length of the ray. /// represents the length of the ray.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void Raycast<VoxelType>::setDirection(const Vector3DFloat& v3dDirection) void Raycast<VolumeType, VoxelType>::setDirection(const Vector3DFloat& v3dDirection)
{ {
m_v3dDirection = v3dDirection; m_v3dDirection = v3dDirection;
} }
@ -62,8 +62,8 @@ namespace PolyVox
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// The result is stored in the RaycastResult instance which was passed to the constructor. /// The result is stored in the RaycastResult instance which was passed to the constructor.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void Raycast<VoxelType>::execute(void) void Raycast<VolumeType, VoxelType>::execute(void)
{ {
//The doRaycast function is assuming that it is iterating over the areas defined between //The doRaycast function is assuming that it is iterating over the areas defined between
//voxels. We actually want to define the areas as being centered on voxels (as this is //voxels. We actually want to define the areas as being centered on voxels (as this is
@ -106,8 +106,8 @@ namespace PolyVox
// It should simply read "if (ty <= tz)". // It should simply read "if (ty <= tz)".
// //
// This error was reported by Joey Hammer (PixelActive). // This error was reported by Joey Hammer (PixelActive).
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void Raycast<VoxelType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2) void Raycast<VolumeType, VoxelType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2)
{ {
int i = (int)floorf(x1); int i = (int)floorf(x1);
int j = (int)floorf(y1); int j = (int)floorf(y1);

View File

@ -26,12 +26,12 @@ freely, subject to the following restrictions:
namespace PolyVox namespace PolyVox
{ {
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
class RaycastWithCallback class RaycastWithCallback
{ {
public: public:
///Constructor ///Constructor
RaycastWithCallback(LargeVolume<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, polyvox_function<bool(const Vector3DInt32& position)> funcCallback); RaycastWithCallback(VolumeType<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, polyvox_function<bool(const Vector3DInt32& position)> funcCallback);
///Sets the start position for the ray. ///Sets the start position for the ray.
void setStart(const Vector3DFloat& v3dStart); void setStart(const Vector3DFloat& v3dStart);
@ -46,8 +46,8 @@ namespace PolyVox
void doRaycast(float x1, float y1, float z1, float x2, float y2, float z2); void doRaycast(float x1, float y1, float z1, float x2, float y2, float z2);
LargeVolume<VoxelType>* m_volData; VolumeType<VoxelType>* m_volData;
typename LargeVolume<VoxelType>::Sampler m_sampVolume; typename VolumeType<VoxelType>::Sampler m_sampVolume;
Vector3DFloat m_v3dStart; Vector3DFloat m_v3dStart;
Vector3DFloat m_v3dDirection; Vector3DFloat m_v3dDirection;

View File

@ -22,8 +22,8 @@ freely, subject to the following restrictions:
*******************************************************************************/ *******************************************************************************/
namespace PolyVox namespace PolyVox
{ {
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
RaycastWithCallback<VoxelType>::RaycastWithCallback(LargeVolume<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, polyvox_function<bool(const Vector3DInt32& position)> funcCallback) RaycastWithCallback<VolumeType, VoxelType>::RaycastWithCallback(VolumeType<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, polyvox_function<bool(const Vector3DInt32& position)> funcCallback)
:m_volData(volData) :m_volData(volData)
,m_sampVolume(volData) ,m_sampVolume(volData)
,m_v3dStart(v3dStart) ,m_v3dStart(v3dStart)
@ -35,20 +35,20 @@ namespace PolyVox
assert(m_funcCallback); assert(m_funcCallback);
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VoxelType>::setStart(const Vector3DFloat& v3dStart) void RaycastWithCallback<VolumeType, VoxelType>::setStart(const Vector3DFloat& v3dStart)
{ {
m_v3dStart = v3dStart; m_v3dStart = v3dStart;
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VoxelType>::setDirection(const Vector3DFloat& v3dDirection) void RaycastWithCallback<VolumeType, VoxelType>::setDirection(const Vector3DFloat& v3dDirection)
{ {
m_v3dDirection = v3dDirection; m_v3dDirection = v3dDirection;
} }
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VoxelType>::execute(void) void RaycastWithCallback<VolumeType, VoxelType>::execute(void)
{ {
//The doRaycast function is assuming that it is iterating over the areas defined between //The doRaycast function is assuming that it is iterating over the areas defined between
//voxels. We actually want to define the areas as being centered on voxels (as this is //voxels. We actually want to define the areas as being centered on voxels (as this is
@ -91,8 +91,8 @@ namespace PolyVox
// It should simply read "if (ty <= tz)". // It should simply read "if (ty <= tz)".
// //
// This error was reported by Joey Hammer (PixelActive). // This error was reported by Joey Hammer (PixelActive).
template <typename VoxelType> template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VoxelType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2) void RaycastWithCallback<VolumeType, VoxelType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2)
{ {
int i = (int)floorf(x1); int i = (int)floorf(x1);
int j = (int)floorf(y1); int j = (int)floorf(y1);