Removing old raycasting code.

This commit is contained in:
David Williams 2012-10-05 16:49:39 +02:00
parent 8c7e2671be
commit bedd09af18
5 changed files with 43 additions and 434 deletions

View File

@ -79,8 +79,6 @@ SET(CORE_INC_FILES
include/PolyVoxCore/RawVolumeSampler.inl
include/PolyVoxCore/Raycast.h
include/PolyVoxCore/Raycast.inl
include/PolyVoxCore/RaycastWithCallback.h
include/PolyVoxCore/RaycastWithCallback.inl
include/PolyVoxCore/Region.h
include/PolyVoxCore/SimpleInterface.h
include/PolyVoxCore/SimpleVolume.h

View File

@ -28,23 +28,17 @@ freely, subject to the following restrictions:
namespace PolyVox
{
/// Stores the result of a raycast operation.
////////////////////////////////////////////////////////////////////////////////
/// A instance of this structure is passed to a Raycast object, and is filled in
/// as the ray traverses the volume. The 'foundIntersection' field indicates whether
/// the ray hit any solid voxels, and if so the 'intersectionVoxel' field indicates
///the voxel's position
////////////////////////////////////////////////////////////////////////////////
struct RaycastResult
namespace MyRaycastResults
{
///Indicates whether an intersection was found
bool foundIntersection;
///If an intersection was found then this field holds the intersecting voxel, otherwise it is undefined.
Vector3DInt32 intersectionVoxel;
Vector3DInt32 previousVoxel;
};
enum MyRaycastResult
{
Completed,
Interupted
};
}
typedef MyRaycastResults::MyRaycastResult MyRaycastResult;
/// The Raycast class can be used to find the fist filled voxel along a given path.
/// OUT OF DATE SINCE UNCLASSING
////////////////////////////////////////////////////////////////////////////////
/// The principle behind raycasting is to fire a 'ray' through the volume and determine
/// what (if anything) that ray hits. This simple test can be used for the purpose of
@ -91,133 +85,12 @@ namespace PolyVox
/// surace extractors. It's behaviour with the Marching Cubes surface extractor has not
/// been tested yet.
////////////////////////////////////////////////////////////////////////////////
template<typename VolumeType>
class Raycast
{
public:
///Constructor
Raycast(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, RaycastResult& result, polyvox_function<bool(const typename VolumeType::Sampler& sampler)> funcIsPassable);
///Sets the start position for the ray.
void setStart(const Vector3DFloat& v3dStart);
///Set the direction for the ray.
void setDirection(const Vector3DFloat& v3dDirectionAndLength);
///Performs the raycast.
void execute();
private:
RaycastResult& m_result;
polyvox_function<bool(const typename VolumeType::Sampler& position)> m_funcIsPassable;
void doRaycast(float x1, float y1, float z1, float x2, float y2, float z2);
VolumeType* m_volData;
typename VolumeType::Sampler m_sampVolume;
Vector3DFloat m_v3dStart;
Vector3DFloat m_v3dDirectionAndLength;
float m_fMaxDistance;
};
namespace MyRaycastResults
{
enum MyRaycastResult
{
Completed,
Interupted
};
}
typedef MyRaycastResults::MyRaycastResult MyRaycastResult;
template<typename VolumeType, typename Callback>
MyRaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback)
{
VolumeType::Sampler sampler(volData);
//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
//what the CubicSurfaceExtractor generates). We add 0.5 here to adjust for this.
float x1 = v3dStart.getX() + 0.5f;
float y1 = v3dStart.getY() + 0.5f;
float z1 = v3dStart.getZ() + 0.5f;
float x2 = v3dEnd.getX() + 0.5f;
float y2 = v3dEnd.getY() + 0.5f;
float z2 = v3dEnd.getZ() + 0.5f;
int i = (int)floorf(x1);
int j = (int)floorf(y1);
int k = (int)floorf(z1);
int iend = (int)floorf(x2);
int jend = (int)floorf(y2);
int kend = (int)floorf(z2);
int di = ((x1 < x2) ? 1 : ((x1 > x2) ? -1 : 0));
int dj = ((y1 < y2) ? 1 : ((y1 > y2) ? -1 : 0));
int dk = ((z1 < z2) ? 1 : ((z1 > z2) ? -1 : 0));
float deltatx = 1.0f / std::abs(x2 - x1);
float deltaty = 1.0f / std::abs(y2 - y1);
float deltatz = 1.0f / std::abs(z2 - z1);
float minx = floorf(x1), maxx = minx + 1.0f;
float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) * deltatx;
float miny = floorf(y1), maxy = miny + 1.0f;
float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) * deltaty;
float minz = floorf(z1), maxz = minz + 1.0f;
float tz = ((z1 > z2) ? (z1 - minz) : (maxz - z1)) * deltatz;
sampler.setPosition(i,j,k);
//m_result.previousVoxel = Vector3DInt32(i,j,k);
for(;;)
{
if(!callback(sampler))
{
//m_result.foundIntersection = true;
//m_result.intersectionVoxel = Vector3DInt32(i,j,k);
return MyRaycastResults::Interupted;
}
//m_result.previousVoxel = Vector3DInt32(i,j,k);
if(tx <= ty && tx <= tz)
{
if(i == iend) break;
tx += deltatx;
i += di;
if(di == 1) sampler.movePositiveX();
if(di == -1) sampler.moveNegativeX();
} else if (ty <= tz)
{
if(j == jend) break;
ty += deltaty;
j += dj;
if(dj == 1) sampler.movePositiveY();
if(dj == -1) sampler.moveNegativeY();
} else
{
if(k == kend) break;
tz += deltatz;
k += dk;
if(dk == 1) sampler.movePositiveZ();
if(dk == -1) sampler.moveNegativeZ();
}
}
return MyRaycastResults::Completed;
}
MyRaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback);
template<typename VolumeType, typename Callback>
MyRaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
{
Vector3DFloat v3dEnd = v3dStart + v3dDirectionAndLength;
return raycastWithEndpoints<VolumeType, Callback>(volData, v3dStart, v3dEnd, callback);
}
MyRaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback);
}
#include "PolyVoxCore/Raycast.inl"

View File

@ -23,63 +23,6 @@ freely, subject to the following restrictions:
namespace PolyVox
{
////////////////////////////////////////////////////////////////////////////////
/// Builds a Raycast object.
/// \param volData A pointer to the volume through which the ray will be cast.
/// \param v3dStart The starting position of the ray.
/// \param v3dDirectionAndLength The direction of the ray. The length of this vector also
/// represents the length of the ray.
/// \param result An instance of RaycastResult in which the result will be stored.
////////////////////////////////////////////////////////////////////////////////
template<typename VolumeType>
Raycast<VolumeType>::Raycast(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, RaycastResult& result, polyvox_function<bool(const typename VolumeType::Sampler& sampler)> funcIsPassable)
:m_result(result)
,m_funcIsPassable(funcIsPassable)
,m_volData(volData)
,m_sampVolume(volData)
,m_v3dStart(v3dStart)
,m_v3dDirectionAndLength(v3dDirectionAndLength)
{
}
////////////////////////////////////////////////////////////////////////////////
/// \param v3dStart The starting position of the ray.
////////////////////////////////////////////////////////////////////////////////
template<typename VolumeType>
void Raycast<VolumeType>::setStart(const Vector3DFloat& v3dStart)
{
m_v3dStart = v3dStart;
}
////////////////////////////////////////////////////////////////////////////////
/// \param v3dDirectionAndLength The direction of the ray. The length of this vector also
/// represents the length of the ray.
////////////////////////////////////////////////////////////////////////////////
template<typename VolumeType>
void Raycast<VolumeType>::setDirection(const Vector3DFloat& v3dDirectionAndLength)
{
//FIXME: We should add a warning when the ray direction is of length one, as this seems to be a common mistake.
m_v3dDirectionAndLength = v3dDirectionAndLength;
}
////////////////////////////////////////////////////////////////////////////////
/// The result is stored in the RaycastResult instance which was passed to the constructor.
////////////////////////////////////////////////////////////////////////////////
template<typename VolumeType>
void Raycast<VolumeType>::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
//what the CubicSurfaceExtractor generates). We add (0.5,0.5,0.5) here to adjust for this.
Vector3DFloat v3dStart = m_v3dStart + Vector3DFloat(0.5f, 0.5f, 0.5f);
//Compute the end point
Vector3DFloat v3dEnd = v3dStart + m_v3dDirectionAndLength;
//Do the raycast
doRaycast(v3dStart.getX(), v3dStart.getY(), v3dStart.getZ(), v3dEnd.getX(), v3dEnd.getY(), v3dEnd.getZ());
}
// This function is based on Christer Ericson's code and description of the 'Uniform Grid Intersection Test' in
// 'Real Time Collision Detection'. The following information from the errata on the book website is also relevent:
//
@ -108,10 +51,22 @@ namespace PolyVox
// page 328. The if-statement that reads "if (ty <= tx && ty <= tz)" has a superfluous condition.
// It should simply read "if (ty <= tz)".
//
// This error was reported by Joey Hammer (PixelActive).
template<typename VolumeType>
void Raycast<VolumeType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2)
// This error was reported by Joey Hammer (PixelActive).
template<typename VolumeType, typename Callback>
MyRaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback)
{
VolumeType::Sampler sampler(volData);
//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
//what the CubicSurfaceExtractor generates). We add 0.5 here to adjust for this.
float x1 = v3dStart.getX() + 0.5f;
float y1 = v3dStart.getY() + 0.5f;
float z1 = v3dStart.getZ() + 0.5f;
float x2 = v3dEnd.getX() + 0.5f;
float y2 = v3dEnd.getY() + 0.5f;
float z2 = v3dEnd.getZ() + 0.5f;
int i = (int)floorf(x1);
int j = (int)floorf(y1);
int k = (int)floorf(z1);
@ -135,18 +90,14 @@ namespace PolyVox
float minz = floorf(z1), maxz = minz + 1.0f;
float tz = ((z1 > z2) ? (z1 - minz) : (maxz - z1)) * deltatz;
m_sampVolume.setPosition(i,j,k);
m_result.previousVoxel = Vector3DInt32(i,j,k);
sampler.setPosition(i,j,k);
for(;;)
{
if(!m_funcIsPassable(m_sampVolume))
if(!callback(sampler))
{
m_result.foundIntersection = true;
m_result.intersectionVoxel = Vector3DInt32(i,j,k);
return;
return MyRaycastResults::Interupted;
}
m_result.previousVoxel = Vector3DInt32(i,j,k);
if(tx <= ty && tx <= tz)
{
@ -154,30 +105,34 @@ namespace PolyVox
tx += deltatx;
i += di;
if(di == 1) m_sampVolume.movePositiveX();
if(di == -1) m_sampVolume.moveNegativeX();
if(di == 1) sampler.movePositiveX();
if(di == -1) sampler.moveNegativeX();
} else if (ty <= tz)
{
if(j == jend) break;
ty += deltaty;
j += dj;
if(dj == 1) m_sampVolume.movePositiveY();
if(dj == -1) m_sampVolume.moveNegativeY();
if(dj == 1) sampler.movePositiveY();
if(dj == -1) sampler.moveNegativeY();
} else
{
if(k == kend) break;
tz += deltatz;
k += dk;
if(dk == 1) m_sampVolume.movePositiveZ();
if(dk == -1) m_sampVolume.moveNegativeZ();
if(dk == 1) sampler.movePositiveZ();
if(dk == -1) sampler.moveNegativeZ();
}
}
//Didn't hit anything
m_result.foundIntersection = false;
m_result.intersectionVoxel = Vector3DInt32(0,0,0);
m_result.previousVoxel = Vector3DInt32(0,0,0);
return MyRaycastResults::Completed;
}
template<typename VolumeType, typename Callback>
MyRaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
{
Vector3DFloat v3dEnd = v3dStart + v3dDirectionAndLength;
return raycastWithEndpoints<VolumeType, Callback>(volData, v3dStart, v3dEnd, callback);
}
}

View File

@ -1,62 +0,0 @@
/*******************************************************************************
Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*******************************************************************************/
#ifndef __PolyVox_RaycastWithCallback_H__
#define __PolyVox_RaycastWithCallback_H__
#include "PolyVoxCore/Vector.h"
namespace PolyVox
{
template<typename VolumeType>
class RaycastWithCallback
{
public:
///Constructor
RaycastWithCallback(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, polyvox_function<bool(const Vector3DInt32& position)> funcCallback);
///Sets the start position for the ray.
void setStart(const Vector3DFloat& v3dStart);
///Set the direction for the ray.
void setDirection(const Vector3DFloat& v3dDirectionAndLength);
///Performs the raycast.
void execute();
private:
polyvox_function<bool(const Vector3DInt32& position)> m_funcCallback;
void doRaycast(float x1, float y1, float z1, float x2, float y2, float z2);
VolumeType* m_volData;
typename VolumeType::Sampler m_sampVolume;
Vector3DFloat m_v3dStart;
Vector3DFloat m_v3dDirectionAndLength;
float m_fMaxDistance;
};
}
#include "PolyVoxCore/RaycastWithCallback.inl"
#endif //__PolyVox_RaycastWithCallback_H__

View File

@ -1,155 +0,0 @@
/*******************************************************************************
Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*******************************************************************************/
namespace PolyVox
{
template<typename VolumeType>
RaycastWithCallback<VolumeType>::RaycastWithCallback(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, polyvox_function<bool(const Vector3DInt32& position)> funcCallback)
:m_volData(volData)
,m_sampVolume(volData)
,m_v3dStart(v3dStart)
,m_v3dDirectionAndLength(v3dDirectionAndLength)
,m_funcCallback(funcCallback)
{
//Check the user provided a callback, because it
//is used to determine when to finish the raycast.
assert(m_funcCallback);
}
template<typename VolumeType>
void RaycastWithCallback<VolumeType>::setStart(const Vector3DFloat& v3dStart)
{
m_v3dStart = v3dStart;
}
template<typename VolumeType>
void RaycastWithCallback<VolumeType>::setDirection(const Vector3DFloat& v3dDirectionAndLength)
{
m_v3dDirectionAndLength = v3dDirectionAndLength;
}
template<typename VolumeType>
void RaycastWithCallback<VolumeType>::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
//what the CubicSurfaceExtractor generates). We add (0.5,0.5,0.5) here to adjust for this.
Vector3DFloat v3dStart = m_v3dStart + Vector3DFloat(0.5f, 0.5f, 0.5f);
//Compute the end point
Vector3DFloat v3dEnd = v3dStart + m_v3dDirectionAndLength;
//Do the raycast
doRaycast(v3dStart.getX(), v3dStart.getY(), v3dStart.getZ(), v3dEnd.getX(), v3dEnd.getY(), v3dEnd.getZ());
}
// This function is based on Christer Ericson's code and description of the 'Uniform Grid Intersection Test' in
// 'Real Time Collision Detection'. The following information from the errata on the book website is also relevent:
//
// pages 326-327. In the function VisitCellsOverlapped() the two lines calculating tx and ty are incorrect.
// The less-than sign in each line should be a greater-than sign. That is, the two lines should read:
//
// float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) / Abs(x2 - x1);
// float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) / Abs(y2 - y1);
//
// Thanks to Jetro Lauha of Fathammer in Helsinki, Finland for reporting this error.
//
// Jetro also points out that the computations of i, j, iend, and jend are incorrectly rounded if the line
// coordinates are allowed to go negative. While that was not really the intent of the code — that is, I
// assumed grids to be numbered from (0, 0) to (m, n) — I'm at fault for not making my assumption clear.
// Where it is important to handle negative line coordinates the computation of these variables should be
// changed to something like this:
//
// // Determine start grid cell coordinates (i, j)
// int i = (int)floorf(x1 / CELL_SIDE);
// int j = (int)floorf(y1 / CELL_SIDE);
//
// // Determine end grid cell coordinates (iend, jend)
// int iend = (int)floorf(x2 / CELL_SIDE);
// int jend = (int)floorf(y2 / CELL_SIDE);
//
// page 328. The if-statement that reads "if (ty <= tx && ty <= tz)" has a superfluous condition.
// It should simply read "if (ty <= tz)".
//
// This error was reported by Joey Hammer (PixelActive).
template<typename VolumeType>
void RaycastWithCallback<VolumeType>::doRaycast(float x1, float y1, float z1, float x2, float y2, float z2)
{
int i = (int)floorf(x1);
int j = (int)floorf(y1);
int k = (int)floorf(z1);
int iend = (int)floorf(x2);
int jend = (int)floorf(y2);
int kend = (int)floorf(z2);
int di = ((x1 < x2) ? 1 : ((x1 > x2) ? -1 : 0));
int dj = ((y1 < y2) ? 1 : ((y1 > y2) ? -1 : 0));
int dk = ((z1 < z2) ? 1 : ((z1 > z2) ? -1 : 0));
float deltatx = 1.0f / std::abs(x2 - x1);
float deltaty = 1.0f / std::abs(y2 - y1);
float deltatz = 1.0f / std::abs(z2 - z1);
float minx = floorf(x1), maxx = minx + 1.0f;
float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) * deltatx;
float miny = floorf(y1), maxy = miny + 1.0f;
float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) * deltaty;
float minz = floorf(z1), maxz = minz + 1.0f;
float tz = ((z1 > z2) ? (z1 - minz) : (maxz - z1)) * deltatz;
m_sampVolume.setPosition(i,j,k);
for(;;)
{
//Call the callback. If it returns false then finish the loop.
if(!m_funcCallback(Vector3DInt32(i,j,k)))
{
break;
}
if(tx <= ty && tx <= tz)
{
tx += deltatx;
i += di;
if(di == 1) m_sampVolume.movePositiveX();
if(di == -1) m_sampVolume.moveNegativeX();
} else if (ty <= tz)
{
ty += deltaty;
j += dj;
if(dj == 1) m_sampVolume.movePositiveY();
if(dj == -1) m_sampVolume.moveNegativeY();
} else
{
tz += deltatz;
k += dk;
if(dk == 1) m_sampVolume.movePositiveZ();
if(dk == -1) m_sampVolume.moveNegativeZ();
}
}
}
}