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
/// is vaid for the path computed by the AStarPathfinder.
template <typename VoxelType>
bool aStarDefaultVoxelValidator(const LargeVolume<VoxelType>* volData, const Vector3DInt32& v3dPos);
template< template<typename> class VolumeType, typename VoxelType>
bool aStarDefaultVoxelValidator(const VolumeType<VoxelType>* volData, const Vector3DInt32& v3dPos);
/// Provides a configuration for the AStarPathfinder.
////////////////////////////////////////////////////////////////////////////////
@ -57,20 +57,20 @@ namespace PolyVox
///
/// \sa AStarPathfinder
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
template< template<typename> class VolumeType, typename VoxelType>
struct AStarPathfinderParams
{
public:
AStarPathfinderParams
(
LargeVolume<VoxelType>* volData,
VolumeType<VoxelType>* volData,
const Vector3DInt32& v3dStart,
const Vector3DInt32& v3dEnd,
std::list<Vector3DInt32>* listResult,
float fHBias = 1.0,
uint32_t uMaxNoOfNodes = 10000,
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
)
:volume(volData)
@ -86,7 +86,7 @@ namespace PolyVox
}
/// 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.
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.
///
/// \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
/// the goal. The progress is reported by computing the distance from the closest node found
@ -159,11 +159,11 @@ namespace PolyVox
///
/// \sa AStarPathfinderParams
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
template< template<typename> class VolumeType, typename VoxelType>
class AStarPathfinder
{
public:
AStarPathfinder(const AStarPathfinderParams<VoxelType>& params);
AStarPathfinder(const AStarPathfinderParams<VolumeType, VoxelType>& params);
void execute();
@ -185,7 +185,7 @@ namespace PolyVox
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.
/// \return true is the voxel is valid for the path
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
bool aStarDefaultVoxelValidator(const LargeVolume<VoxelType>* volData, const Vector3DInt32& v3dPos)
template< template<typename> class VolumeType, typename VoxelType>
bool aStarDefaultVoxelValidator(const VolumeType<VoxelType>* volData, const Vector3DInt32& v3dPos)
{
//Voxels are considered valid candidates for the path if they are inside the volume...
if(volData->getEnclosingRegion().containsPoint(v3dPos) == false)
@ -52,14 +52,14 @@ namespace PolyVox
////////////////////////////////////////////////////////////////////////////////
// AStarPathfinder Class
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
AStarPathfinder<VoxelType>::AStarPathfinder(const AStarPathfinderParams<VoxelType>& params)
template< template<typename> class VolumeType, typename VoxelType>
AStarPathfinder<VolumeType, VoxelType>::AStarPathfinder(const AStarPathfinderParams<VolumeType, VoxelType>& params)
:m_params(params)
{
}
template <typename VoxelType>
void AStarPathfinder<VoxelType>::execute()
template< template<typename> class VolumeType, typename VoxelType>
void AStarPathfinder<VolumeType, VoxelType>::execute()
{
//Clear any existing nodes
allNodes.clear();
@ -191,8 +191,8 @@ namespace PolyVox
}
}
template <typename VoxelType>
void AStarPathfinder<VoxelType>::processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal)
template< template<typename> class VolumeType, typename VoxelType>
void AStarPathfinder<VolumeType, VoxelType>::processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal)
{
bool bIsVoxelValidForPath = m_params.isVoxelValidForPath(m_params.volume, neighbourPos);
if(!bIsVoxelValidForPath)
@ -247,8 +247,8 @@ namespace PolyVox
}
}
template <typename VoxelType>
float AStarPathfinder<VoxelType>::SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
template< template<typename> class VolumeType, typename VoxelType>
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.
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;
}
template <typename VoxelType>
float AStarPathfinder<VoxelType>::EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
template< template<typename> class VolumeType, typename VoxelType>
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
//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);
}
template <typename VoxelType>
float AStarPathfinder<VoxelType>::TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
template< template<typename> class VolumeType, typename VoxelType>
float AStarPathfinder<VolumeType, VoxelType>::TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
{
//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.
@ -288,8 +288,8 @@ namespace PolyVox
return cornerSteps * sqrt_3 + edgeSteps * sqrt_2 + faceSteps * sqrt_1;
}
template <typename VoxelType>
float AStarPathfinder<VoxelType>::computeH(const Vector3DInt32& a, const Vector3DInt32& b)
template< template<typename> class VolumeType, typename VoxelType>
float AStarPathfinder<VolumeType, VoxelType>::computeH(const Vector3DInt32& a, const Vector3DInt32& b)
{
float hVal;

View File

@ -29,19 +29,19 @@ freely, subject to the following restrictions:
namespace PolyVox
{
template <typename VoxelType>
template< template<typename> class VolumeType, typename VoxelType>
class AmbientOcclusionCalculator
{
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();
void execute(void);
private:
Region m_region;
typename LargeVolume<VoxelType>::Sampler m_sampVolume;
LargeVolume<VoxelType>* m_volInput;
typename VolumeType<VoxelType>::Sampler m_sampVolume;
VolumeType<VoxelType>* m_volInput;
Array<3, uint8_t>* m_arrayResult;
float m_fRayLength;

View File

@ -28,10 +28,12 @@ freely, subject to the following restrictions:
#include "PolyVoxImpl/RandomUnitVectors.h"
#include "PolyVoxImpl/RandomVectors.h"
#include <algorithm>
namespace PolyVox
{
template <typename VoxelType>
AmbientOcclusionCalculator<VoxelType>::AmbientOcclusionCalculator(LargeVolume<VoxelType>* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement)
template< template<typename> class VolumeType, typename VoxelType>
AmbientOcclusionCalculator<VolumeType, VoxelType>::AmbientOcclusionCalculator(VolumeType<VoxelType>* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement)
:m_region(region)
,m_sampVolume(volInput)
,m_volInput(volInput)
@ -54,18 +56,18 @@ namespace PolyVox
mIndexIncreament = 1;
}
template <typename VoxelType>
AmbientOcclusionCalculator<VoxelType>::~AmbientOcclusionCalculator()
template< template<typename> class VolumeType, typename VoxelType>
AmbientOcclusionCalculator<VolumeType, VoxelType>::~AmbientOcclusionCalculator()
{
}
template <typename VoxelType>
void AmbientOcclusionCalculator<VoxelType>::execute(void)
template< template<typename> class VolumeType, typename VoxelType>
void AmbientOcclusionCalculator<VolumeType, VoxelType>::execute(void)
{
const int iRatioX = m_volInput->getWidth() / m_arrayResult->getDimension(0);
const int iRatioY = m_volInput->getHeight() / m_arrayResult->getDimension(1);
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 fRatioY = iRatioY;
@ -82,7 +84,7 @@ namespace PolyVox
const Vector3DFloat v3dOffset(0.5f,0.5f,0.5f);
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
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
/// been tested yet.
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
template< template<typename> class VolumeType, typename VoxelType>
class Raycast
{
public:
///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.
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);
LargeVolume<VoxelType>* m_volData;
typename LargeVolume<VoxelType>::Sampler m_sampVolume;
VolumeType<VoxelType>* m_volData;
typename VolumeType<VoxelType>::Sampler m_sampVolume;
Vector3DFloat m_v3dStart;
Vector3DFloat m_v3dDirection;

View File

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

View File

@ -26,12 +26,12 @@ freely, subject to the following restrictions:
namespace PolyVox
{
template <typename VoxelType>
template< template<typename> class VolumeType, typename VoxelType>
class RaycastWithCallback
{
public:
///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.
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);
LargeVolume<VoxelType>* m_volData;
typename LargeVolume<VoxelType>::Sampler m_sampVolume;
VolumeType<VoxelType>* m_volData;
typename VolumeType<VoxelType>::Sampler m_sampVolume;
Vector3DFloat m_v3dStart;
Vector3DFloat m_v3dDirection;

View File

@ -22,8 +22,8 @@ freely, subject to the following restrictions:
*******************************************************************************/
namespace PolyVox
{
template <typename VoxelType>
RaycastWithCallback<VoxelType>::RaycastWithCallback(LargeVolume<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, polyvox_function<bool(const Vector3DInt32& position)> funcCallback)
template< template<typename> class VolumeType, typename VoxelType>
RaycastWithCallback<VolumeType, VoxelType>::RaycastWithCallback(VolumeType<VoxelType>* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, polyvox_function<bool(const Vector3DInt32& position)> funcCallback)
:m_volData(volData)
,m_sampVolume(volData)
,m_v3dStart(v3dStart)
@ -35,20 +35,20 @@ namespace PolyVox
assert(m_funcCallback);
}
template <typename VoxelType>
void RaycastWithCallback<VoxelType>::setStart(const Vector3DFloat& v3dStart)
template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VolumeType, VoxelType>::setStart(const Vector3DFloat& v3dStart)
{
m_v3dStart = v3dStart;
}
template <typename VoxelType>
void RaycastWithCallback<VoxelType>::setDirection(const Vector3DFloat& v3dDirection)
template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VolumeType, VoxelType>::setDirection(const Vector3DFloat& v3dDirection)
{
m_v3dDirection = v3dDirection;
}
template <typename VoxelType>
void RaycastWithCallback<VoxelType>::execute(void)
template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VolumeType, VoxelType>::execute(void)
{
//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
@ -91,8 +91,8 @@ namespace PolyVox
// It should simply read "if (ty <= tz)".
//
// This error was reported by Joey Hammer (PixelActive).
template <typename VoxelType>
void RaycastWithCallback<VoxelType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2)
template< template<typename> class VolumeType, typename VoxelType>
void RaycastWithCallback<VolumeType, VoxelType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2)
{
int i = (int)floorf(x1);
int j = (int)floorf(y1);