Merge branch 'develop' into feature/cmake-cxx11-detect
Conflicts: examples/Basic/CMakeLists.txt examples/OpenGL/CMakeLists.txt examples/Paging/CMakeLists.txt examples/SmoothLOD/CMakeLists.txt library/PolyVoxCore/include/PolyVoxCore/Impl/TypeDef.h
This commit is contained in:
@ -32,9 +32,7 @@ SET(CORE_SRC_FILES
|
||||
source/ArraySizes.cpp
|
||||
source/AStarPathfinder.cpp
|
||||
source/Log.cpp
|
||||
source/MeshDecimator.cpp
|
||||
source/Region.cpp
|
||||
source/SimpleInterface.cpp
|
||||
source/VertexTypes.cpp
|
||||
)
|
||||
|
||||
@ -73,8 +71,6 @@ SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
|
||||
include/PolyVoxCore/Material.h
|
||||
include/PolyVoxCore/MaterialDensityPair.h
|
||||
include/PolyVoxCore/MeshDecimator.h
|
||||
include/PolyVoxCore/MeshDecimator.inl
|
||||
include/PolyVoxCore/PolyVoxForwardDeclarations.h
|
||||
include/PolyVoxCore/RawVolume.h
|
||||
include/PolyVoxCore/RawVolume.inl
|
||||
@ -82,7 +78,6 @@ SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/Raycast.h
|
||||
include/PolyVoxCore/Raycast.inl
|
||||
include/PolyVoxCore/Region.h
|
||||
include/PolyVoxCore/SimpleInterface.h
|
||||
include/PolyVoxCore/SimpleVolume.h
|
||||
include/PolyVoxCore/SimpleVolume.inl
|
||||
include/PolyVoxCore/SimpleVolumeBlock.inl
|
||||
|
@ -98,6 +98,8 @@ namespace PolyVox
|
||||
AmbientOcclusionCalculatorRaycastCallback<IsVoxelTransparentCallback> ambientOcclusionCalculatorRaycastCallback(isVoxelTransparentCallback);
|
||||
RaycastResult result = raycastWithDirection(volInput, v3dRayStart, v3dRayDirection, ambientOcclusionCalculatorRaycastCallback);
|
||||
|
||||
// Note - The performance of this could actually be improved it we exited as soon
|
||||
// as the ray left the volume. The raycast test has an example of how to do this.
|
||||
if(result == RaycastResults::Completed)
|
||||
{
|
||||
++uVisibleDirections;
|
||||
|
@ -38,6 +38,16 @@ namespace PolyVox
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// More details to come...
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace WrapModes
|
||||
{
|
||||
enum WrapMode
|
||||
{
|
||||
Clamp = 0,
|
||||
Border = 1
|
||||
};
|
||||
}
|
||||
typedef WrapModes::WrapMode WrapMode;
|
||||
|
||||
template <typename _VoxelType>
|
||||
class BaseVolume
|
||||
{
|
||||
@ -55,9 +65,12 @@ namespace PolyVox
|
||||
Vector3DInt32 getPosition(void) const;
|
||||
inline VoxelType getVoxel(void) const;
|
||||
|
||||
bool isCurrentPositionValid(void) const;
|
||||
|
||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
||||
inline bool setVoxel(VoxelType tValue);
|
||||
void setWrapMode(WrapMode eWrapMode, VoxelType tBorder = VoxelType(0));
|
||||
|
||||
void movePositiveX(void);
|
||||
void movePositiveY(void);
|
||||
@ -98,12 +111,23 @@ namespace PolyVox
|
||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||
|
||||
protected:
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
|
||||
DerivedVolumeType* mVolume;
|
||||
|
||||
//The current position in the volume
|
||||
int32_t mXPosInVolume;
|
||||
int32_t mYPosInVolume;
|
||||
int32_t mZPosInVolume;
|
||||
|
||||
WrapMode m_eWrapMode;
|
||||
VoxelType m_tBorder;
|
||||
|
||||
//Whether the current position is inside the volume
|
||||
//FIXME - Replace these with flags
|
||||
bool m_bIsCurrentPositionValidInX;
|
||||
bool m_bIsCurrentPositionValidInY;
|
||||
bool m_bIsCurrentPositionValidInZ;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -111,7 +135,7 @@ namespace PolyVox
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a Region representing the extents of the Volume.
|
||||
Region getEnclosingRegion(void) const;
|
||||
const Region& getEnclosingRegion(void) const;
|
||||
/// Gets the width of the volume in voxels.
|
||||
int32_t getWidth(void) const;
|
||||
/// Gets the height of the volume in voxels.
|
||||
@ -125,9 +149,17 @@ namespace PolyVox
|
||||
/// Gets the length of the diagonal in voxels
|
||||
float getDiagonalLength(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxel(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
@ -159,6 +191,9 @@ namespace PolyVox
|
||||
int32_t m_uLongestSideLength;
|
||||
int32_t m_uShortestSideLength;
|
||||
float m_fDiagonalLength;
|
||||
|
||||
//The border value
|
||||
VoxelType m_tBorderValue;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
BaseVolume<VoxelType>::BaseVolume(const Region& regValid)
|
||||
:m_regValidRegion(regValid)
|
||||
,m_tBorderValue(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -76,15 +77,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getBorderValue(void) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
return m_tBorderValue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return A Region representing the extent of the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
Region BaseVolume<VoxelType>::getEnclosingRegion(void) const
|
||||
const Region& BaseVolume<VoxelType>::getEnclosingRegion(void) const
|
||||
{
|
||||
return m_regValidRegion;
|
||||
}
|
||||
@ -153,6 +153,30 @@ namespace PolyVox
|
||||
return m_fDiagonalLength;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
@ -177,13 +201,37 @@ namespace PolyVox
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getVoxelWithWrapping(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& /*v3dPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void BaseVolume<VoxelType>::setBorderValue(const VoxelType& /*tBorder*/)
|
||||
void BaseVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||
{
|
||||
assert(false);
|
||||
m_tBorderValue = tBorder;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -21,6 +21,8 @@ freely, subject to the following restrictions:
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "PolyVoxCore/Impl/Utility.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
@ -30,6 +32,11 @@ namespace PolyVox
|
||||
,mXPosInVolume(0)
|
||||
,mYPosInVolume(0)
|
||||
,mZPosInVolume(0)
|
||||
,m_eWrapMode(WrapModes::Border)
|
||||
,m_tBorder(0)
|
||||
,m_bIsCurrentPositionValidInX(false)
|
||||
,m_bIsCurrentPositionValidInY(false)
|
||||
,m_bIsCurrentPositionValidInZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -53,13 +60,18 @@ namespace PolyVox
|
||||
return mVolume->getVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
bool inline BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::isCurrentPositionValid(void) const
|
||||
{
|
||||
return m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(const Vector3DInt32& v3dNewPos)
|
||||
{
|
||||
mXPosInVolume = v3dNewPos.getX();
|
||||
mYPosInVolume = v3dNewPos.getY();
|
||||
mZPosInVolume = v3dNewPos.getZ();
|
||||
setPosition(v3dNewPos.getX(), v3dNewPos.getY(), v3dNewPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -69,6 +81,10 @@ namespace PolyVox
|
||||
mXPosInVolume = xPos;
|
||||
mYPosInVolume = yPos;
|
||||
mZPosInVolume = zPos;
|
||||
|
||||
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(xPos);
|
||||
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(yPos);
|
||||
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(zPos);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -78,11 +94,20 @@ namespace PolyVox
|
||||
return mVolume->setVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume, tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setWrapMode(WrapMode eWrapMode, VoxelType tBorder)
|
||||
{
|
||||
m_eWrapMode = eWrapMode;
|
||||
m_tBorder = tBorder;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveX(void)
|
||||
{
|
||||
mXPosInVolume++;
|
||||
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -90,6 +115,7 @@ namespace PolyVox
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveY(void)
|
||||
{
|
||||
mYPosInVolume++;
|
||||
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -97,6 +123,7 @@ namespace PolyVox
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveZ(void)
|
||||
{
|
||||
mZPosInVolume++;
|
||||
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -104,6 +131,7 @@ namespace PolyVox
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeX(void)
|
||||
{
|
||||
mXPosInVolume--;
|
||||
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -111,6 +139,7 @@ namespace PolyVox
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeY(void)
|
||||
{
|
||||
mYPosInVolume--;
|
||||
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -118,69 +147,70 @@ namespace PolyVox
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeZ(void)
|
||||
{
|
||||
mZPosInVolume--;
|
||||
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -189,63 +219,63 @@ namespace PolyVox
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -254,62 +284,101 @@ namespace PolyVox
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume );
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
return getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
if(mVolume->getEnclosingRegion().containsPoint(uXPos, uYPos, uZPos))
|
||||
{
|
||||
return mVolume->getVoxelAt(uXPos, uYPos, uZPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(m_eWrapMode)
|
||||
{
|
||||
case WrapModes::Clamp:
|
||||
{
|
||||
const Vector3DInt32& lowerCorner = mVolume->m_regValidRegion.getLowerCorner();
|
||||
const Vector3DInt32& upperCorner = mVolume->m_regValidRegion.getUpperCorner();
|
||||
|
||||
int32_t iClampedX = clamp(uXPos, lowerCorner.getX(), upperCorner.getX());
|
||||
int32_t iClampedY = clamp(uYPos, lowerCorner.getY(), upperCorner.getY());
|
||||
int32_t iClampedZ = clamp(uZPos, lowerCorner.getZ(), upperCorner.getZ());
|
||||
|
||||
return mVolume->getVoxelAt(iClampedX, iClampedY, iClampedZ);
|
||||
//No need to break as we've returned
|
||||
}
|
||||
case WrapModes::Border:
|
||||
{
|
||||
return m_tBorder;
|
||||
//No need to break as we've returned
|
||||
}
|
||||
default:
|
||||
{
|
||||
//Should never happen
|
||||
assert(false);
|
||||
return VoxelType(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ freely, subject to the following restrictions:
|
||||
#include "PolyVoxForwardDeclarations.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
|
||||
@ -109,7 +110,7 @@ namespace PolyVox
|
||||
};
|
||||
|
||||
public:
|
||||
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
||||
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(0), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
||||
|
||||
|
||||
void execute();
|
||||
@ -145,6 +146,10 @@ namespace PolyVox
|
||||
//This constant defines the maximum number of quads which can share a
|
||||
//vertex in a cubic style mesh. See the initialisation for more details.
|
||||
static const uint32_t MaxVerticesPerPosition;
|
||||
|
||||
//The wrap mode
|
||||
WrapMode m_eWrapMode;
|
||||
typename VolumeType::VoxelType m_tBorderValue;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -35,11 +35,13 @@ namespace PolyVox
|
||||
const uint32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::MaxVerticesPerPosition = 6;
|
||||
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
||||
CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
||||
:m_volData(volData)
|
||||
,m_regSizeInVoxels(region)
|
||||
,m_meshCurrent(result)
|
||||
,m_bMergeQuads(bMergeQuads)
|
||||
,m_eWrapMode(eWrapMode)
|
||||
,m_tBorderValue(tBorderValue)
|
||||
{
|
||||
m_funcIsQuadNeededCallback = isQuadNeeded;
|
||||
}
|
||||
@ -68,6 +70,7 @@ namespace PolyVox
|
||||
m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2);
|
||||
|
||||
typename VolumeType::Sampler volumeSampler(m_volData);
|
||||
volumeSampler.setWrapMode(m_eWrapMode, m_tBorderValue);
|
||||
|
||||
for(int32_t z = m_regSizeInVoxels.getLowerCorner().getZ(); z <= m_regSizeInVoxels.getUpperCorner().getZ(); z++)
|
||||
{
|
||||
|
@ -27,6 +27,7 @@ freely, subject to the following restrictions:
|
||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
|
||||
namespace PolyVox
|
||||
@ -35,7 +36,7 @@ namespace PolyVox
|
||||
class CubicSurfaceExtractorWithNormals
|
||||
{
|
||||
public:
|
||||
CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
||||
CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(0), IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
||||
|
||||
void execute();
|
||||
|
||||
@ -51,6 +52,10 @@ namespace PolyVox
|
||||
|
||||
//Information about the region we are currently processing
|
||||
Region m_regSizeInVoxels;
|
||||
|
||||
//The wrap mode
|
||||
WrapMode m_eWrapMode;
|
||||
typename VolumeType::VoxelType m_tBorderValue;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,13 @@ freely, subject to the following restrictions:
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
CubicSurfaceExtractorWithNormals<VolumeType, IsQuadNeeded>::CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, IsQuadNeeded isQuadNeeded)
|
||||
CubicSurfaceExtractorWithNormals<VolumeType, IsQuadNeeded>::CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, IsQuadNeeded isQuadNeeded)
|
||||
:m_volData(volData)
|
||||
,m_sampVolume(volData)
|
||||
,m_meshCurrent(result)
|
||||
,m_regSizeInVoxels(region)
|
||||
,m_eWrapMode(eWrapMode)
|
||||
,m_tBorderValue(tBorderValue)
|
||||
{
|
||||
m_funcIsQuadNeededCallback = isQuadNeeded;
|
||||
}
|
||||
@ -51,7 +53,7 @@ namespace PolyVox
|
||||
|
||||
uint32_t material = 0;
|
||||
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z), m_volData->getVoxelAt(x+1,y,z), material))
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelWithWrapping(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxelWithWrapping(x+1,y,z,m_eWrapMode,m_tBorderValue), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
@ -61,7 +63,7 @@ namespace PolyVox
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x+1,y,z), m_volData->getVoxelAt(x,y,z), material))
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelWithWrapping(x+1,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxelWithWrapping(x,y,z,m_eWrapMode,m_tBorderValue), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
@ -72,7 +74,7 @@ namespace PolyVox
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z), m_volData->getVoxelAt(x,y+1,z), material))
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelWithWrapping(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxelWithWrapping(x,y+1,z,m_eWrapMode,m_tBorderValue), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast<float>(material)));
|
||||
@ -82,7 +84,7 @@ namespace PolyVox
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y+1,z), m_volData->getVoxelAt(x,y,z), material))
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelWithWrapping(x,y+1,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxelWithWrapping(x,y,z,m_eWrapMode,m_tBorderValue), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast<float>(material)));
|
||||
@ -93,7 +95,7 @@ namespace PolyVox
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z), m_volData->getVoxelAt(x,y,z+1), material))
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelWithWrapping(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxelWithWrapping(x,y,z+1,m_eWrapMode,m_tBorderValue), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast<float>(material)));
|
||||
@ -103,7 +105,7 @@ namespace PolyVox
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z+1), m_volData->getVoxelAt(x,y,z), material))
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelWithWrapping(x,y,z+1,m_eWrapMode,m_tBorderValue), m_volData->getVoxelWithWrapping(x,y,z,m_eWrapMode,m_tBorderValue), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast<float>(material)));
|
||||
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
||||
#ifndef __PolyVox_DefaultIsQuadNeeded_H__
|
||||
#define __PolyVox_DefaultIsQuadNeeded_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
|
@ -24,38 +24,40 @@ freely, subject to the following restrictions:
|
||||
#ifndef __PolyVox_MarchingCubesController_H__
|
||||
#define __PolyVox_MarchingCubesController_H__
|
||||
|
||||
#include "PolyVoxCore/BaseVolume.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// This class provides a default implementation of a controller for the MarchingCubesSurfaceExtractor. It controls the behaviour of the
|
||||
/// MarchingCubesSurfaceExtractor and provides the required properties from the underlying voxel type.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// PolyVox does not enforce any requirements regarding what data must be present in a voxel, and instead allows any primitive or user-defined
|
||||
/// type to be used. However, the Marching Cubes algorithm does have some requirents about the underlying data in that conceptually it operates
|
||||
/// on a <i>density field</i>. In addition, the PolyVox implementation of the Marching Cubes algorithm also understands the idea of each voxel
|
||||
/// having a material which is copied into the vertex data.
|
||||
///
|
||||
/// Because we want the MarchingCubesSurfaceExtractor to work on <i>any</i> voxel type, we use a <i>Marching Cubes controller</i> (passed as
|
||||
/// a parameter of the MarchingCubesSurfaceExtractor) to expose the required properties. This parameter defaults to the DefaultMarchingCubesController.
|
||||
/// The main implementation of this class is designed to work with primitives data types, and the class is also specialised for the Material,
|
||||
/// Density and MaterialdensityPair classes.
|
||||
///
|
||||
/// If you create a custom class for your voxel data then you probably want to include a specialisation of DefaultMarchingCubesController,
|
||||
/// though you don't have to if you don't want to use the Marching Cubes algorithm or if you prefer to define a seperate Marching Cubes controller
|
||||
/// and pass it as an explicit parameter (rather than relying on the default).
|
||||
///
|
||||
/// For primitive types, the DefaultMarchingCubesController considers the value of the voxel to represent it's density and just returns a constant
|
||||
/// for the material. So you can, for example, run the MarchingCubesSurfaceExtractor on a volume of floats or ints.
|
||||
///
|
||||
/// It is possible to customise the behaviour of the controller by providing a threshold value through the constructor. The extracted surface
|
||||
/// will pass through the density value specified by the threshold, and so you should make sure that the threshold value you choose is between
|
||||
/// the minimum and maximum values found in your volume data. By default it is in the middle of the representable range of the underlying type.
|
||||
///
|
||||
/// \sa MarchingCubesSurfaceExtractor
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* This class provides a default implementation of a controller for the MarchingCubesSurfaceExtractor. It controls the behaviour of the
|
||||
* MarchingCubesSurfaceExtractor and provides the required properties from the underlying voxel type.
|
||||
*
|
||||
* PolyVox does not enforce any requirements regarding what data must be present in a voxel, and instead allows any primitive or user-defined
|
||||
* type to be used. However, the Marching Cubes algorithm does have some requirents about the underlying data in that conceptually it operates
|
||||
* on a <i>density field</i>. In addition, the PolyVox implementation of the Marching Cubes algorithm also understands the idea of each voxel
|
||||
* having a material which is copied into the vertex data.
|
||||
*
|
||||
* Because we want the MarchingCubesSurfaceExtractor to work on <i>any</i> voxel type, we use a <i>Marching Cubes controller</i> (passed as
|
||||
* a parameter of the MarchingCubesSurfaceExtractor) to expose the required properties. This parameter defaults to the DefaultMarchingCubesController.
|
||||
* The main implementation of this class is designed to work with primitives data types, and the class is also specialised for the Material,
|
||||
* Density and MaterialdensityPair classes.
|
||||
*
|
||||
* If you create a custom class for your voxel data then you probably want to include a specialisation of DefaultMarchingCubesController,
|
||||
* though you don't have to if you don't want to use the Marching Cubes algorithm or if you prefer to define a seperate Marching Cubes controller
|
||||
* and pass it as an explicit parameter (rather than relying on the default).
|
||||
*
|
||||
* For primitive types, the DefaultMarchingCubesController considers the value of the voxel to represent it's density and just returns a constant
|
||||
* for the material. So you can, for example, run the MarchingCubesSurfaceExtractor on a volume of floats or ints.
|
||||
*
|
||||
* It is possible to customise the behaviour of the controller by providing a threshold value through the constructor. The extracted surface
|
||||
* will pass through the density value specified by the threshold, and so you should make sure that the threshold value you choose is between
|
||||
* the minimum and maximum values found in your volume data. By default it is in the middle of the representable range of the underlying type.
|
||||
*
|
||||
* \sa MarchingCubesSurfaceExtractor
|
||||
*
|
||||
*/
|
||||
template<typename VoxelType>
|
||||
class DefaultMarchingCubesController
|
||||
{
|
||||
@ -67,63 +69,57 @@ namespace PolyVox
|
||||
/// but this is not really desirable on modern hardware. We'll probably come back to material representation in the future.
|
||||
typedef float MaterialType;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructor
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// This version of the constructor takes no parameters and sets the threshold to the middle of the representable range of the underlying type.
|
||||
/// For example, if the voxel type is 'uint8_t' then the representable range is 0-255, and the threshold will be set to 127. On the other hand,
|
||||
/// if the voxel type is 'float' then the representable range is -FLT_MAX to FLT_MAX and the threshold will be set to zero.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* This version of the constructor takes no parameters and sets the threshold to the middle of the representable range of the underlying type.
|
||||
* For example, if the voxel type is 'uint8_t' then the representable range is 0-255, and the threshold will be set to 127. On the other hand,
|
||||
* if the voxel type is 'float' then the representable range is -FLT_MAX to FLT_MAX and the threshold will be set to zero.
|
||||
*/
|
||||
DefaultMarchingCubesController(void)
|
||||
{
|
||||
m_tThreshold = ((std::numeric_limits<DensityType>::min)() + (std::numeric_limits<DensityType>::max)()) / 2;
|
||||
:m_tThreshold(((std::numeric_limits<DensityType>::min)() + (std::numeric_limits<DensityType>::max)()) / 2)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructor
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// This version of the constructor allows you to set a custom threshold.
|
||||
/// \param tThreshold The threshold to use.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
DefaultMarchingCubesController(DensityType tThreshold)
|
||||
{
|
||||
m_tThreshold = tThreshold;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Converts the underlying voxel type into a density value.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The default implementation of this function just returns the voxel type directly and is suitable for primitives types. Specialisations of
|
||||
/// this class can modify this behaviour.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Converts the underlying voxel type into a density value.
|
||||
*
|
||||
* The default implementation of this function just returns the voxel type directly and is suitable for primitives types. Specialisations of
|
||||
* this class can modify this behaviour.
|
||||
*/
|
||||
DensityType convertToDensity(VoxelType voxel)
|
||||
{
|
||||
return voxel;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Converts the underlying voxel type into a material value.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The default implementation of this function just returns the constant '1'. There's not much else it can do, as it needs to work with primitive
|
||||
/// types and the actual value of the type is already being considered to be the density. Specialisations of this class can modify this behaviour.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Converts the underlying voxel type into a material value.
|
||||
*
|
||||
* The default implementation of this function just returns the constant '1'. There's not much else it can do, as it needs to work with primitive
|
||||
* types and the actual value of the type is already being considered to be the density. Specialisations of this class can modify this behaviour.
|
||||
*/
|
||||
MaterialType convertToMaterial(VoxelType /*voxel*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the density value which was passed to the constructor.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// As mentioned in the class description, the extracted surface will pass through the density value specified by the threshold, and so you
|
||||
/// should make sure that the threshold value you choose is between the minimum and maximum values found in your volume data. By default it
|
||||
///is in the middle of the representable range of the underlying type.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Returns the density value which was passed to the constructor.
|
||||
*
|
||||
* As mentioned in the class description, the extracted surface will pass through the density value specified by the threshold, and so you
|
||||
* should make sure that the threshold value you choose is between the minimum and maximum values found in your volume data. By default it
|
||||
* is in the middle of the representable range of the underlying type.
|
||||
*/
|
||||
DensityType getThreshold(void)
|
||||
{
|
||||
return m_tThreshold;
|
||||
}
|
||||
|
||||
void setThreshold(DensityType tThreshold)
|
||||
{
|
||||
m_tThreshold = tThreshold;
|
||||
}
|
||||
|
||||
private:
|
||||
DensityType m_tThreshold;
|
||||
};
|
||||
|
@ -177,6 +177,11 @@ namespace PolyVox
|
||||
return m_tThreshold;
|
||||
}
|
||||
|
||||
void setThreshold(DensityType tThreshold)
|
||||
{
|
||||
m_tThreshold = tThreshold;
|
||||
}
|
||||
|
||||
private:
|
||||
DensityType m_tThreshold;
|
||||
};
|
||||
|
@ -46,6 +46,13 @@ freely, subject to the following restrictions:
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined SWIG
|
||||
//Do nothing in this case
|
||||
#else
|
||||
#undef POLYVOX_DEPRECATED
|
||||
#define POLYVOX_DEPRECATED //Define it to nothing to avoid warnings
|
||||
#endif
|
||||
|
||||
// Now we use the generic helper definitions above to define POLYVOX_API and POLYVOX_LOCAL.
|
||||
// POLYVOX_API is used for the public API symbols. It either imports or exports (or does nothing for static build)
|
||||
// POLYVOX_LOCAL is used for non-api symbols.
|
||||
@ -95,7 +102,7 @@ freely, subject to the following restrictions:
|
||||
//In this case we can just use static_assert
|
||||
#else
|
||||
#include <boost/static_assert.hpp>
|
||||
#define static_assert BOOST_STATIC_ASSERT
|
||||
#define static_assert(condition, message) BOOST_STATIC_ASSERT(condition)
|
||||
#endif
|
||||
|
||||
#if defined(HAS_CXX11_CSTDINT_H)
|
||||
|
@ -1,37 +1,58 @@
|
||||
/*******************************************************************************
|
||||
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_Utility_H__
|
||||
#define __PolyVox_Utility_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
POLYVOX_API uint8_t logBase2(uint32_t uInput);
|
||||
POLYVOX_API bool isPowerOf2(uint32_t uInput);
|
||||
}
|
||||
|
||||
#endif
|
||||
/*******************************************************************************
|
||||
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_Utility_H__
|
||||
#define __PolyVox_Utility_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
POLYVOX_API uint8_t logBase2(uint32_t uInput);
|
||||
POLYVOX_API bool isPowerOf2(uint32_t uInput);
|
||||
|
||||
int32_t roundTowardsNegInf(float r);
|
||||
int32_t roundToInteger(float r);
|
||||
template <typename Type>
|
||||
Type clamp(const Type& value, const Type& low, const Type& high);
|
||||
|
||||
inline int32_t roundTowardsNegInf(float r)
|
||||
{
|
||||
return (r > 0.0) ? static_cast<int32_t>(r) : static_cast<int32_t>(r - 1.0f);
|
||||
}
|
||||
|
||||
inline int32_t roundToNearestInteger(float r)
|
||||
{
|
||||
return (r > 0.0) ? static_cast<int32_t>(r + 0.5f) : static_cast<int32_t>(r - 0.5f);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type clamp(const Type& value, const Type& low, const Type& high)
|
||||
{
|
||||
return (std::min)(high, (std::max)(low, value));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -166,6 +166,7 @@ namespace PolyVox
|
||||
//in the future
|
||||
//typedef Volume<VoxelType> VolumeOfVoxelType; //Workaround for GCC/VS2010 differences.
|
||||
//class Sampler : public VolumeOfVoxelType::template Sampler< LargeVolume<VoxelType> >
|
||||
#ifndef SWIG
|
||||
#if defined(_MSC_VER)
|
||||
class Sampler : public BaseVolume<VoxelType>::Sampler< LargeVolume<VoxelType> > //This line works on VS2010
|
||||
#else
|
||||
@ -176,9 +177,8 @@ namespace PolyVox
|
||||
Sampler(LargeVolume<VoxelType>* volume);
|
||||
~Sampler();
|
||||
|
||||
Sampler& operator=(const Sampler& rhs);
|
||||
|
||||
VoxelType getSubSampledVoxel(uint8_t uLevel) const;
|
||||
/// \deprecated
|
||||
POLYVOX_DEPRECATED VoxelType getSubSampledVoxel(uint8_t uLevel) const;
|
||||
inline VoxelType getVoxel(void) const;
|
||||
|
||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||
@ -243,6 +243,7 @@ namespace PolyVox
|
||||
Block<VoxelType> block;
|
||||
uint32_t timestamp;
|
||||
};
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// Constructor for creating a very large paging volume.
|
||||
@ -264,12 +265,18 @@ namespace PolyVox
|
||||
/// Destructor
|
||||
~LargeVolume();
|
||||
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxel(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
|
||||
//Sets whether or not blocks are compressed in memory
|
||||
void setCompressionEnabled(bool bCompressionEnabled);
|
||||
@ -277,8 +284,6 @@ namespace PolyVox
|
||||
void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks);
|
||||
/// Sets the number of blocks which can be in memory before the paging system starts unloading them
|
||||
void setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory);
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
@ -305,6 +310,22 @@ namespace PolyVox
|
||||
LargeVolume& operator=(const LargeVolume& rhs);
|
||||
|
||||
private:
|
||||
|
||||
struct BlockPositionCompare
|
||||
{
|
||||
bool operator() (const PolyVox::Vector3DInt32& a, const PolyVox::Vector3DInt32& b)
|
||||
{
|
||||
const uint32_t size = 3;
|
||||
for(uint32_t ct = 0; ct < size; ++ct)
|
||||
{
|
||||
if (a.getElement(ct) < b.getElement(ct))
|
||||
return true;
|
||||
if (b.getElement(ct) < a.getElement(ct))
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
void initialise(const Region& regValidRegion, uint16_t uBlockSideLength);
|
||||
|
||||
/// gets called when a new region is allocated and needs to be filled
|
||||
@ -318,12 +339,12 @@ namespace PolyVox
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataOverflowHandler;
|
||||
|
||||
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||
void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const;
|
||||
void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock) const;
|
||||
/// this function can be called by m_funcDataRequiredHandler without causing any weird effects
|
||||
bool setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const;
|
||||
|
||||
//The block data
|
||||
mutable std::map<Vector3DInt32, LoadedBlock > m_pBlocks;
|
||||
mutable std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare> m_pBlocks;
|
||||
|
||||
//The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
|
||||
//than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
|
||||
@ -336,12 +357,6 @@ namespace PolyVox
|
||||
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
||||
uint32_t m_uMaxNumberOfBlocksInMemory;
|
||||
|
||||
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
||||
//block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a
|
||||
//good chance we'll often hit it anyway. It's a chunk of homogenous data (rather than a single value) so that
|
||||
//the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume.
|
||||
VoxelType* m_pUncompressedBorderData;
|
||||
|
||||
//The size of the volume
|
||||
Region m_regValidRegionInBlocks;
|
||||
|
||||
|
@ -95,7 +95,6 @@ namespace PolyVox
|
||||
LargeVolume<VoxelType>::~LargeVolume()
|
||||
{
|
||||
flushAll();
|
||||
delete[] m_pUncompressedBorderData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -112,14 +111,37 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an atempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::getBorderValue(void) const
|
||||
VoxelType LargeVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
return *m_pUncompressedBorderData;
|
||||
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
|
||||
|
||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t xOffset = static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos) const
|
||||
{
|
||||
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -147,7 +169,7 @@ namespace PolyVox
|
||||
}
|
||||
else
|
||||
{
|
||||
return getBorderValue();
|
||||
return this->getBorderValue();
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,6 +183,62 @@ namespace PolyVox
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||
{
|
||||
switch(eWrapMode)
|
||||
{
|
||||
case WrapModes::Clamp:
|
||||
{
|
||||
//Perform clamping
|
||||
uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
|
||||
uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
|
||||
uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
|
||||
uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
|
||||
uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
|
||||
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
|
||||
|
||||
//Get the voxel value
|
||||
return getVoxel(uXPos, uYPos, uZPos);
|
||||
//No need to break as we've returned
|
||||
}
|
||||
case WrapModes::Border:
|
||||
{
|
||||
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
|
||||
{
|
||||
return getVoxel(uXPos, uYPos, uZPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tBorder;
|
||||
}
|
||||
//No need to break as we've returned
|
||||
}
|
||||
default:
|
||||
{
|
||||
//Should never happen
|
||||
assert(false);
|
||||
return VoxelType(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||
{
|
||||
return getVoxelWithWrapping(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Enabling compression allows significantly more data to be stored in memory.
|
||||
/// \param bCompressionEnabled Specifies whether compression is enabled.
|
||||
@ -213,17 +291,6 @@ namespace PolyVox
|
||||
m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||
{
|
||||
/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
|
||||
return pUncompressedBorderBlock->fill(tBorder);*/
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos the \c x position of the voxel
|
||||
/// \param uYPos the \c y position of the voxel
|
||||
@ -297,7 +364,7 @@ namespace PolyVox
|
||||
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||
{
|
||||
Vector3DInt32 pos(x,y,z);
|
||||
typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
|
||||
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos);
|
||||
|
||||
if(itBlock != m_pBlocks.end())
|
||||
{
|
||||
@ -328,7 +395,7 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::flushAll()
|
||||
{
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i;
|
||||
//Replaced the for loop here as the call to
|
||||
//eraseBlock was invalidating the iterator.
|
||||
while(m_pBlocks.size() > 0)
|
||||
@ -362,7 +429,7 @@ namespace PolyVox
|
||||
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||
{
|
||||
Vector3DInt32 pos(x,y,z);
|
||||
typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
|
||||
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos);
|
||||
if(itBlock == m_pBlocks.end())
|
||||
{
|
||||
// not loaded, not unloading
|
||||
@ -414,7 +481,6 @@ namespace PolyVox
|
||||
m_uTimestamper = 0;
|
||||
m_uMaxNumberOfUncompressedBlocks = 16;
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_pUncompressedBorderData = 0;
|
||||
m_uMaxNumberOfBlocksInMemory = 1024;
|
||||
m_v3dLastAccessedBlockPos = Vector3DInt32(0,0,0); //There are no invalid positions, but initially the m_pLastAccessedBlock pointer will be null;
|
||||
m_pLastAccessedBlock = 0;
|
||||
@ -422,25 +488,25 @@ namespace PolyVox
|
||||
|
||||
this->m_regValidRegion = regValidRegion;
|
||||
|
||||
m_regValidRegionInBlocks.setLowerCorner(this->m_regValidRegion.getLowerCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
//Compute the block side length
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
||||
|
||||
m_regValidRegionInBlocks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setLowerY(this->m_regValidRegion.getLowerY() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setLowerZ(this->m_regValidRegion.getLowerZ() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperX(this->m_regValidRegion.getUpperX() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperY(this->m_regValidRegion.getUpperY() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperZ(this->m_regValidRegion.getUpperZ() >> m_uBlockSideLengthPower);
|
||||
|
||||
setMaxNumberOfUncompressedBlocks(m_uMaxNumberOfUncompressedBlocks);
|
||||
|
||||
//Clear the previous data
|
||||
m_pBlocks.clear();
|
||||
|
||||
//Compute the block side length
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
||||
|
||||
//Clear the previous data
|
||||
m_pBlocks.clear();
|
||||
|
||||
//Create the border block
|
||||
m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType());
|
||||
|
||||
//Other properties we might find useful later
|
||||
this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
@ -448,7 +514,7 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const
|
||||
void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock) const
|
||||
{
|
||||
if(m_funcDataOverflowHandler)
|
||||
{
|
||||
@ -519,7 +585,7 @@ namespace PolyVox
|
||||
return m_pLastAccessedBlock;
|
||||
}
|
||||
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
||||
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
||||
// check whether the block is already loaded
|
||||
if(itBlock == m_pBlocks.end())
|
||||
{
|
||||
@ -532,8 +598,8 @@ namespace PolyVox
|
||||
if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
// find the least recently used block
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
|
||||
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i;
|
||||
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itUnloadBlock = m_pBlocks.begin();
|
||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||
{
|
||||
if(i->second.timestamp < itUnloadBlock->second.timestamp)
|
||||
@ -622,8 +688,8 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
float LargeVolume<VoxelType>::calculateCompressionRatio(void)
|
||||
{
|
||||
float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType);
|
||||
float fCompressedSize = calculateSizeInBytes();
|
||||
float fRawSize = static_cast<float>(m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType));
|
||||
float fCompressedSize = static_cast<float>(calculateSizeInBytes());
|
||||
return fCompressedSize/fRawSize;
|
||||
}
|
||||
|
||||
@ -636,7 +702,7 @@ namespace PolyVox
|
||||
uint32_t uSizeInBytes = sizeof(LargeVolume);
|
||||
|
||||
//Memory used by the blocks
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i;
|
||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||
{
|
||||
//Inaccurate - account for rest of loaded block.
|
||||
@ -647,12 +713,6 @@ namespace PolyVox
|
||||
uSizeInBytes += m_vecUncompressedBlockCache.capacity() * sizeof(LoadedBlock);
|
||||
uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
|
||||
//Memory used by border data.
|
||||
if(m_pUncompressedBorderData)
|
||||
{
|
||||
uSizeInBytes += m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
}
|
||||
|
||||
return uSizeInBytes;
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,12 @@ freely, subject to the following restrictions:
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#define BORDER_LOW(x) ((( x >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != x)
|
||||
#define BORDER_HIGH(x) ((( (x+1) >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != (x+1))
|
||||
//#define BORDER_LOW(x) (( x % mVolume->m_uBlockSideLength) != 0)
|
||||
//#define BORDER_HIGH(x) (( x % mVolume->m_uBlockSideLength) != mVolume->m_uBlockSideLength - 1)
|
||||
#define CAN_GO_NEG_X(val) ((val > this->mVolume->getEnclosingRegion().getLowerCorner().getX()) && (val % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_POS_X(val) ((val < this->mVolume->getEnclosingRegion().getUpperCorner().getX()) && ((val + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_NEG_Y(val) ((val > this->mVolume->getEnclosingRegion().getLowerCorner().getY()) && (val % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_POS_Y(val) ((val < this->mVolume->getEnclosingRegion().getUpperCorner().getY()) && ((val + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_NEG_Z(val) ((val > this->mVolume->getEnclosingRegion().getLowerCorner().getZ()) && (val % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_POS_Z(val) ((val < this->mVolume->getEnclosingRegion().getUpperCorner().getZ()) && ((val + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
@ -39,21 +41,6 @@ namespace PolyVox
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
typename LargeVolume<VoxelType>::Sampler& LargeVolume<VoxelType>::Sampler::operator=(const typename LargeVolume<VoxelType>::Sampler& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
this->mVolume = rhs.mVolume;
|
||||
this->mXPosInVolume = rhs.mXPosInVolume;
|
||||
this->mYPosInVolume = rhs.mYPosInVolume;
|
||||
this->mZPosInVolume = rhs.mZPosInVolume;
|
||||
mCurrentVoxel = rhs.mCurrentVoxel;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::getSubSampledVoxel(uint8_t uLevel) const
|
||||
{
|
||||
@ -95,7 +82,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::getVoxel(void) const
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
if(this->isCurrentPositionValid())
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getVoxelAt(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -107,38 +101,47 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||
{
|
||||
this->mXPosInVolume = xPos;
|
||||
this->mYPosInVolume = yPos;
|
||||
this->mZPosInVolume = zPos;
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >::setPosition(xPos, yPos, zPos);
|
||||
|
||||
const int32_t uXBlock = this->mXPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uYBlock = this->mYPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uZBlock = this->mZPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t uXPosInBlock = static_cast<uint16_t>(this->mXPosInVolume - (uXBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uYPosInBlock = static_cast<uint16_t>(this->mYPosInVolume - (uYBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uZPosInBlock = static_cast<uint16_t>(this->mZPosInVolume - (uZBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
|
||||
const uint32_t uVoxelIndexInBlock = uXPosInBlock +
|
||||
uYPosInBlock * this->mVolume->m_uBlockSideLength +
|
||||
uZPosInBlock * this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
|
||||
if(this->mVolume->m_regValidRegionInBlocks.containsPoint(Vector3DInt32(uXBlock, uYBlock, uZBlock)))
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid())
|
||||
{
|
||||
const int32_t uXBlock = this->mXPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uYBlock = this->mYPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uZBlock = this->mZPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t uXPosInBlock = static_cast<uint16_t>(this->mXPosInVolume - (uXBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uYPosInBlock = static_cast<uint16_t>(this->mYPosInVolume - (uYBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uZPosInBlock = static_cast<uint16_t>(this->mZPosInVolume - (uZBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
|
||||
const uint32_t uVoxelIndexInBlock = uXPosInBlock +
|
||||
uYPosInBlock * this->mVolume->m_uBlockSideLength +
|
||||
uZPosInBlock * this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
|
||||
Block<VoxelType>* pUncompressedCurrentBlock = this->mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock);
|
||||
|
||||
mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentVoxel = this->mVolume->m_pUncompressedBorderData + uVoxelIndexInBlock;
|
||||
mCurrentVoxel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
bool LargeVolume<VoxelType>::Sampler::setVoxel(VoxelType tValue)
|
||||
{
|
||||
//*mCurrentVoxel = tValue;
|
||||
/*if(m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ)
|
||||
{
|
||||
*mCurrentVoxel = tValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}*/
|
||||
|
||||
//Need to think what effect this has on any existing iterators.
|
||||
assert(false);
|
||||
return false;
|
||||
@ -147,8 +150,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::movePositiveX(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mXPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >::movePositiveX();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mXPosInVolume) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
++mCurrentVoxel;
|
||||
@ -163,8 +172,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::movePositiveY(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mYPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >::movePositiveY();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mYPosInVolume) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength;
|
||||
@ -179,8 +194,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::movePositiveZ(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mZPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >::movePositiveZ();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mZPosInVolume) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
@ -195,8 +216,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::moveNegativeX(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mXPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >::moveNegativeX();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mXPosInVolume + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
--mCurrentVoxel;
|
||||
@ -211,8 +238,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::moveNegativeY(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mYPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >::moveNegativeY();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mYPosInVolume + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength;
|
||||
@ -227,8 +260,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::moveNegativeZ(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mZPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >::moveNegativeZ();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mZPosInVolume + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
@ -243,91 +282,91 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -335,87 +374,91 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
if((this->isCurrentPositionValid()))
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -423,93 +466,97 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
}
|
||||
|
||||
#undef BORDER_LOW
|
||||
#undef BORDER_HIGH
|
||||
#undef CAN_GO_NEG_X
|
||||
#undef CAN_GO_POS_X
|
||||
#undef CAN_GO_NEG_Y
|
||||
#undef CAN_GO_POS_Y
|
||||
#undef CAN_GO_NEG_Z
|
||||
#undef CAN_GO_POS_Z
|
||||
|
@ -28,6 +28,7 @@ freely, subject to the following restrictions:
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
#include "PolyVoxCore/DefaultMarchingCubesController.h"
|
||||
|
||||
@ -37,7 +38,7 @@ namespace PolyVox
|
||||
class MarchingCubesSurfaceExtractor
|
||||
{
|
||||
public:
|
||||
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, Controller controller = Controller());
|
||||
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(0), Controller controller = Controller());
|
||||
|
||||
void execute();
|
||||
|
||||
@ -189,7 +190,7 @@ namespace PolyVox
|
||||
SurfaceMesh<PositionMaterialNormal>* m_meshCurrent;
|
||||
|
||||
//Information about the region we are currently processing
|
||||
const Region m_regSizeInVoxels;
|
||||
Region m_regSizeInVoxels;
|
||||
Region m_regSizeInCells;
|
||||
/*Region m_regSizeInVoxelsCropped;
|
||||
Region m_regSizeInVoxelsUncropped;
|
||||
@ -201,7 +202,7 @@ namespace PolyVox
|
||||
Controller m_controller;
|
||||
|
||||
//Our threshold value
|
||||
const typename Controller::DensityType m_tThreshold;
|
||||
typename Controller::DensityType m_tThreshold;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename VolumeType, typename Controller>
|
||||
MarchingCubesSurfaceExtractor<VolumeType, Controller>::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, Controller controller)
|
||||
MarchingCubesSurfaceExtractor<VolumeType, Controller>::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller)
|
||||
:m_volData(volData)
|
||||
,m_sampVolume(volData)
|
||||
,m_meshCurrent(result)
|
||||
@ -35,6 +35,8 @@ namespace PolyVox
|
||||
//m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion());
|
||||
m_regSizeInCells = m_regSizeInVoxels;
|
||||
m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1));
|
||||
|
||||
m_sampVolume.setWrapMode(eWrapMode, tBorderValue);
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename Controller>
|
||||
|
@ -42,6 +42,10 @@ namespace PolyVox
|
||||
{
|
||||
public:
|
||||
MaterialDensityPair() : m_uMaterial(0), m_uDensity(0) {}
|
||||
|
||||
// FIXME - This is a bit odd... we need to allow the MaterialDensityPair to be initialised with a single integer
|
||||
// because PolyVox often initialises voxels by calling VoxelType(0). Is there a better way we should handle this?
|
||||
MaterialDensityPair(Type tValue) : m_uMaterial(tValue), m_uDensity(tValue) {}
|
||||
MaterialDensityPair(Type uMaterial, Type uDensity) : m_uMaterial(uMaterial), m_uDensity(uDensity) {}
|
||||
|
||||
bool operator==(const MaterialDensityPair& rhs) const
|
||||
@ -135,7 +139,12 @@ namespace PolyVox
|
||||
DensityType getThreshold(void)
|
||||
{
|
||||
return m_tThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
void setThreshold(DensityType tThreshold)
|
||||
{
|
||||
m_tThreshold = tThreshold;
|
||||
}
|
||||
|
||||
private:
|
||||
DensityType m_tThreshold;
|
||||
|
@ -1,187 +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_MeshDecimator_H__
|
||||
#define __PolyVox_MeshDecimator_H__
|
||||
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
#include "PolyVoxCore/VertexTypes.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// The MeshDecimator reduces the number of triangles in a mesh.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Meshes generated by the PolyVox surface extractors typically have a very high
|
||||
/// number of triangles in them. This can pose difficulties both for the rendering
|
||||
/// storage of such meshes. The MeshDecimator provides a way of reducing the triangle
|
||||
/// count with minimal visual effect.
|
||||
///
|
||||
/// The MeshDecimator is based on the principle of edge collapse, and currently works
|
||||
/// with meshes generated by the MarchingCubesSurfaceExtractor or CubicSurfaceExtractor. It does
|
||||
/// not work with meshes generated by the CubicSurfaceExtractorWithNormals, although
|
||||
/// this may be addressed in the future. The algorithm iterates over each pair of
|
||||
/// connected vertices in the mesh and attemps to determine if they can be collapsed
|
||||
/// into a single vertex.
|
||||
///
|
||||
/// The main criteria used in deciding whether two vertices can collapse is whether
|
||||
/// they have the same normal. In the case of the cubic surfaces the normals must be
|
||||
/// exactly the same, whereas in the case of the Marching Cubes surfaces a threshold
|
||||
/// is used to determine whether two normals are 'close enough'. Additional constraints
|
||||
/// apply to vertices which lie on the edges of regions or on the boundary between two
|
||||
/// regions - these vertices are much less likely to be collapsed.
|
||||
///
|
||||
/// Given a mesh called 'mesh', you can create a decimated version as follows:
|
||||
/// \code
|
||||
/// SurfaceMesh<PositionMaterial> decimatedMesh;
|
||||
/// MeshDecimator<PositionMaterial> decimator(&mesh, &decimatedMesh);
|
||||
/// decimator.execute();
|
||||
/// \endcode
|
||||
///
|
||||
/// The above applies for a cubic mesh, for a Marching Cubes mesh you need to parametise
|
||||
/// the MeshDecimator and resulting SurfaceMesh on the 'PositionMaterialNormal' type
|
||||
/// instead of the 'PositionMaterial' type.
|
||||
///
|
||||
/// \deprecated
|
||||
template <typename VertexType>
|
||||
class MeshDecimator
|
||||
{
|
||||
//Used to keep track of when a vertex is
|
||||
//on one or more faces of the region
|
||||
enum RegionFaceFlags
|
||||
{
|
||||
RFF_ON_REGION_FACE_NEG_X,
|
||||
RFF_ON_REGION_FACE_POS_X ,
|
||||
RFF_ON_REGION_FACE_NEG_Y ,
|
||||
RFF_ON_REGION_FACE_POS_Y ,
|
||||
RFF_ON_REGION_FACE_NEG_Z ,
|
||||
RFF_ON_REGION_FACE_POS_Z,
|
||||
RFF_NO_OF_REGION_FACE_FLAGS
|
||||
};
|
||||
|
||||
//Data about the initial mesh - this
|
||||
//will be fill in once at the start
|
||||
struct InitialVertexMetadata
|
||||
{
|
||||
Vector3DFloat normal;
|
||||
bool isOnMaterialEdge;
|
||||
std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> isOnRegionFace;
|
||||
};
|
||||
|
||||
//Representing a triangle for decimation purposes.
|
||||
struct Triangle
|
||||
{
|
||||
uint32_t v0;
|
||||
uint32_t v1;
|
||||
uint32_t v2;
|
||||
Vector3DFloat normal;
|
||||
};
|
||||
|
||||
struct IntVertex
|
||||
{
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t z;
|
||||
uint32_t index;
|
||||
|
||||
IntVertex(int32_t xVal, int32_t yVal, int32_t zVal, uint32_t indexVal)
|
||||
:x(xVal)
|
||||
,y(yVal)
|
||||
,z(zVal)
|
||||
,index(indexVal)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const IntVertex& rhs) const
|
||||
{
|
||||
return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
|
||||
}
|
||||
|
||||
bool operator<(const IntVertex& rhs) const
|
||||
{
|
||||
if (z < rhs.z)
|
||||
return true;
|
||||
if (rhs.z < z)
|
||||
return false;
|
||||
|
||||
if (y < rhs.y)
|
||||
return true;
|
||||
if (rhs.y < y)
|
||||
return false;
|
||||
|
||||
if (x < rhs.x)
|
||||
return true;
|
||||
if (rhs.x < x)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
///Constructor
|
||||
POLYVOX_DEPRECATED MeshDecimator(const SurfaceMesh<VertexType>* pInputMesh, SurfaceMesh<VertexType>* pOutputMesh, float fEdgeCollapseThreshold = 0.95f);
|
||||
|
||||
///Performs the decimation.
|
||||
POLYVOX_DEPRECATED void execute();
|
||||
|
||||
private:
|
||||
|
||||
void fillInitialVertexMetadata(std::vector<InitialVertexMetadata>& vecInitialVertexMetadata);
|
||||
|
||||
void buildConnectivityData(void);
|
||||
|
||||
bool attemptEdgeCollapse(uint32_t uSrc, uint32_t uDst);
|
||||
|
||||
const SurfaceMesh<VertexType>* m_pInputMesh;
|
||||
SurfaceMesh<VertexType>* m_pOutputMesh;
|
||||
|
||||
uint32_t performDecimationPass(float m_fMinDotProductForCollapse);
|
||||
bool isSubset(std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> a, std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> b);
|
||||
|
||||
bool canCollapseEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool canCollapseMaterialEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold);
|
||||
|
||||
//Data structures used during decimation
|
||||
|
||||
std::vector<bool> vertexLocked;
|
||||
std::vector<uint32_t> vertexMapper;
|
||||
|
||||
std::vector<Triangle> m_vecTriangles;
|
||||
std::vector< std::vector<uint32_t> > trianglesUsingVertex; //Should probably use vector of vectors, and resise in advance.
|
||||
|
||||
std::vector<InitialVertexMetadata> m_vecInitialVertexMetadata;
|
||||
|
||||
float m_fMinDotProductForCollapse;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/MeshDecimator.inl"
|
||||
|
||||
#endif //__PolyVox_MeshDecimator_H__
|
@ -1,347 +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
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Builds a MeshDecimator.
|
||||
/// \param pInputMesh A pointer to the mesh to be decimated.
|
||||
/// \param[out] pOutputMesh A pointer to where the result should be stored. Any existing
|
||||
/// contents will be deleted.
|
||||
/// \param fEdgeCollapseThreshold This is only use in the case of a Marching Cubes
|
||||
/// surface and controls how close two normals must be to collapse. The dot product
|
||||
/// between the normals is computed and compared to this threshold. A threshold of
|
||||
/// 1.0 means nothing will collapse, a threshold of 0.0 means everything will collapse.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VertexType>
|
||||
MeshDecimator<VertexType>::MeshDecimator(const SurfaceMesh<VertexType>* pInputMesh, SurfaceMesh<VertexType>* pOutputMesh, float fEdgeCollapseThreshold)
|
||||
:m_pInputMesh(pInputMesh)
|
||||
,m_pOutputMesh(pOutputMesh)
|
||||
,m_fMinDotProductForCollapse(fEdgeCollapseThreshold)
|
||||
{
|
||||
*m_pOutputMesh = *m_pInputMesh;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void MeshDecimator<VertexType>::execute()
|
||||
{
|
||||
//Sanity check.
|
||||
if((m_pOutputMesh->m_vecVertices.empty()) || (m_pOutputMesh->m_vecTriangleIndices.empty()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
buildConnectivityData();
|
||||
fillInitialVertexMetadata(m_vecInitialVertexMetadata);
|
||||
|
||||
uint32_t noOfEdgesCollapsed;
|
||||
do
|
||||
{
|
||||
noOfEdgesCollapsed = performDecimationPass(m_fMinDotProductForCollapse);
|
||||
m_pOutputMesh->removeDegenerateTris();
|
||||
if(noOfEdgesCollapsed > 0)
|
||||
{
|
||||
//Build the connectivity data for the next pass. If this is slow, then look
|
||||
//at adjusting it (based on vertex mapper?) rather than bulding from scratch.
|
||||
buildConnectivityData();
|
||||
}
|
||||
}while(noOfEdgesCollapsed > 0);
|
||||
|
||||
m_pOutputMesh->removeUnusedVertices();
|
||||
|
||||
//Decimation will have invalidated LOD levels.
|
||||
m_pOutputMesh->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = m_pOutputMesh->getNoOfIndices();
|
||||
m_pOutputMesh->m_vecLodRecords.push_back(lodRecord);
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void MeshDecimator<VertexType>::buildConnectivityData(void)
|
||||
{
|
||||
//Build a list of all the triangles, complete with face normals.
|
||||
m_vecTriangles.clear();
|
||||
m_vecTriangles.resize(m_pOutputMesh->m_vecTriangleIndices.size() / 3);
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangles.size(); triCt++)
|
||||
{
|
||||
m_vecTriangles[triCt].v0 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 0];
|
||||
m_vecTriangles[triCt].v1 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 1];
|
||||
m_vecTriangles[triCt].v2 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 2];
|
||||
|
||||
Vector3DFloat v0Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v0].position;
|
||||
Vector3DFloat v1Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v1].position;
|
||||
Vector3DFloat v2Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v2].position;
|
||||
|
||||
Vector3DFloat v0v1 = v1Pos - v0Pos;
|
||||
Vector3DFloat v0v2 = v2Pos - v0Pos;
|
||||
Vector3DFloat normal = v0v1.cross(v0v2);
|
||||
normal.normalise();
|
||||
|
||||
m_vecTriangles[triCt].normal = normal;
|
||||
}
|
||||
|
||||
//For each vertex, determine which triangles are using it.
|
||||
trianglesUsingVertex.clear();
|
||||
trianglesUsingVertex.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
for(uint32_t ct = 0; ct < trianglesUsingVertex.size(); ct++)
|
||||
{
|
||||
trianglesUsingVertex[ct].reserve(6);
|
||||
}
|
||||
for(uint32_t ct = 0; ct < m_vecTriangles.size(); ct++)
|
||||
{
|
||||
trianglesUsingVertex[m_vecTriangles[ct].v0].push_back(ct);
|
||||
trianglesUsingVertex[m_vecTriangles[ct].v1].push_back(ct);
|
||||
trianglesUsingVertex[m_vecTriangles[ct].v2].push_back(ct);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t MeshDecimator<VertexType>::performDecimationPass(float /*m_fMinDotProductForCollapse*/)
|
||||
{
|
||||
// Count how many edges we have collapsed
|
||||
uint32_t noOfEdgesCollapsed = 0;
|
||||
|
||||
// The vertex mapper track whick vertices collapse onto which.
|
||||
vertexMapper.clear();
|
||||
vertexMapper.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
|
||||
// Once a vertex is involved in a collapse (either because it
|
||||
// moves onto a different vertex, or because a different vertex
|
||||
// moves onto it) it is forbidden to take part in another collapse
|
||||
// this pass. We enforce this by setting the vertex locked flag.
|
||||
vertexLocked.clear();
|
||||
vertexLocked.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
|
||||
// Initialise the vectors
|
||||
for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++)
|
||||
{
|
||||
// Initiall all vertices points to themselves
|
||||
vertexMapper[ct] = ct;
|
||||
// All vertices are initially unlocked
|
||||
vertexLocked[ct] = false;
|
||||
}
|
||||
|
||||
//For each triangle...
|
||||
for(uint32_t ctIter = 0; ctIter < m_vecTriangles.size(); ctIter++)
|
||||
{
|
||||
if(attemptEdgeCollapse(m_vecTriangles[ctIter].v0, m_vecTriangles[ctIter].v1))
|
||||
{
|
||||
++noOfEdgesCollapsed;
|
||||
}
|
||||
|
||||
if(attemptEdgeCollapse(m_vecTriangles[ctIter].v1, m_vecTriangles[ctIter].v2))
|
||||
{
|
||||
++noOfEdgesCollapsed;
|
||||
}
|
||||
|
||||
if(attemptEdgeCollapse(m_vecTriangles[ctIter].v2, m_vecTriangles[ctIter].v0))
|
||||
{
|
||||
++noOfEdgesCollapsed;
|
||||
}
|
||||
}
|
||||
|
||||
if(noOfEdgesCollapsed > 0)
|
||||
{
|
||||
//Fix up the indices
|
||||
for(uint32_t triCt = 0; triCt < m_pOutputMesh->m_vecTriangleIndices.size(); triCt++)
|
||||
{
|
||||
uint32_t before = m_pOutputMesh->m_vecTriangleIndices[triCt];
|
||||
uint32_t after = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]];
|
||||
if(before != after)
|
||||
{
|
||||
m_pOutputMesh->m_vecTriangleIndices[triCt] = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return noOfEdgesCollapsed;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::attemptEdgeCollapse(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
//A vertex will be locked if it has already been involved in a collapse this pass.
|
||||
if(vertexLocked[uSrc] || vertexLocked[uDst])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(canCollapseEdge(uSrc, uDst))
|
||||
{
|
||||
//Move v0 onto v1
|
||||
vertexMapper[uSrc] = uDst; //vertexMapper[v1];
|
||||
vertexLocked[uSrc] = true;
|
||||
vertexLocked[uDst] = true;
|
||||
|
||||
//Increment the counter
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::canCollapseEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
bool bCanCollapse = true;
|
||||
|
||||
if(m_vecInitialVertexMetadata[uSrc].isOnMaterialEdge)
|
||||
{
|
||||
bCanCollapse &= canCollapseMaterialEdge(uSrc, uDst);
|
||||
}
|
||||
|
||||
if(m_vecInitialVertexMetadata[uSrc].isOnRegionFace.any())
|
||||
{
|
||||
bCanCollapse &= canCollapseRegionEdge(uSrc, uDst);
|
||||
}
|
||||
|
||||
if(bCanCollapse) //Only bother with this if the earlier tests passed.
|
||||
{
|
||||
bCanCollapse &= canCollapseNormalEdge(uSrc, uDst);
|
||||
}
|
||||
|
||||
return bCanCollapse;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
// We can collapse normal vertices onto edge vertices, and edge vertices
|
||||
// onto corner vertices, but not vice-versa. Hence we check whether all
|
||||
// the edge flags in the source vertex are also set in the destination vertex.
|
||||
if(isSubset(m_vecInitialVertexMetadata[uSrc].isOnRegionFace, m_vecInitialVertexMetadata[uDst].isOnRegionFace) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// In general adjacent regions surface meshes may collapse differently
|
||||
// and this can cause cracks. We solve this by only allowing the collapse
|
||||
// is the normals are exactly the same. We do not use the user provided
|
||||
// tolerence here (but do allow for floating point error).
|
||||
if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[uDst].normal) < 0.999f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::canCollapseMaterialEdge(uint32_t /*uSrc*/, uint32_t /*uDst*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//This function should really use some work. For a start we already have the
|
||||
//faces normals for the input mesh yet we are computing them on the fly here.
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold)
|
||||
{
|
||||
bool faceFlipped = false;
|
||||
std::vector<uint32_t>& triangles = trianglesUsingVertex[uSrc];
|
||||
|
||||
for(std::vector<uint32_t>::iterator triIter = triangles.begin(); triIter != triangles.end(); triIter++)
|
||||
{
|
||||
uint32_t tri = *triIter;
|
||||
|
||||
const uint32_t& v0Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3];
|
||||
const uint32_t& v1Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 1];
|
||||
const uint32_t& v2Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 2];
|
||||
|
||||
//Check if degenerate
|
||||
if((v0Old == v1Old) || (v1Old == v2Old) || (v2Old == v0Old))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t v0New = v0Old;
|
||||
uint32_t v1New = v1Old;
|
||||
uint32_t v2New = v2Old;
|
||||
|
||||
if(v0New == uSrc)
|
||||
v0New = uDst;
|
||||
if(v1New == uSrc)
|
||||
v1New = uDst;
|
||||
if(v2New == uSrc)
|
||||
v2New = uDst;
|
||||
|
||||
//Check if degenerate
|
||||
if((v0New == v1New) || (v1New == v2New) || (v2New == v0New))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Vector3DFloat& v0OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition(); //Note: we need the vertex mapper here. These neighbouring vertices may have been moved.
|
||||
const Vector3DFloat& v1OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1Old]].getPosition();
|
||||
const Vector3DFloat& v2OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition();
|
||||
|
||||
const Vector3DFloat& v0NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0New]].getPosition();
|
||||
const Vector3DFloat& v1NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1New]].getPosition();
|
||||
const Vector3DFloat& v2NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2New]].getPosition();
|
||||
|
||||
Vector3DFloat OldNormal = (v1OldPos - v0OldPos).cross(v2OldPos - v1OldPos);
|
||||
Vector3DFloat NewNormal = (v1NewPos - v0NewPos).cross(v2NewPos - v1NewPos);
|
||||
|
||||
OldNormal.normalise();
|
||||
NewNormal.normalise();
|
||||
|
||||
float dotProduct = OldNormal.dot(NewNormal);
|
||||
//NOTE: I don't think we should be using the threshold here, we're just checking for a complete face flip
|
||||
if(dotProduct < fThreshold)
|
||||
{
|
||||
//cout << " Face flipped!!" << endl;
|
||||
|
||||
faceFlipped = true;
|
||||
|
||||
/*vertexLocked[v0] = true;
|
||||
vertexLocked[v1] = true;*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return faceFlipped;
|
||||
}
|
||||
|
||||
// Returns true if every bit which is set in 'a' is also set in 'b'. The reverse does not need to be true.
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::isSubset(std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> a, std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> b)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
for(int ct = 0; ct < RFF_NO_OF_REGION_FACE_FLAGS; ct++)
|
||||
{
|
||||
if(a.test(ct))
|
||||
{
|
||||
if(b.test(ct) == false)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -127,6 +127,11 @@ namespace PolyVox
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class Region;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SimpleVolume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType> class SimpleVolume;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MarchingCubesSurfaceExtractor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -104,14 +104,9 @@ namespace PolyVox
|
||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||
|
||||
private:
|
||||
|
||||
//Other current position information
|
||||
VoxelType* mCurrentVoxel;
|
||||
|
||||
//Whether the current position is inside the volume
|
||||
//FIXME - Replace these with flags
|
||||
bool m_bIsCurrentPositionValidInX;
|
||||
bool m_bIsCurrentPositionValidInY;
|
||||
bool m_bIsCurrentPositionValidInZ;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -122,15 +117,19 @@ namespace PolyVox
|
||||
/// Destructor
|
||||
~RawVolume();
|
||||
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxel(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
@ -151,9 +150,6 @@ namespace PolyVox
|
||||
|
||||
//The block data
|
||||
VoxelType* m_pData;
|
||||
|
||||
//The border value
|
||||
VoxelType m_tBorderValue;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace PolyVox
|
||||
RawVolume<VoxelType>::RawVolume(const Region& regValid)
|
||||
:BaseVolume<VoxelType>(regValid)
|
||||
{
|
||||
setBorderValue(VoxelType());
|
||||
this->setBorderValue(VoxelType());
|
||||
|
||||
//Create a volume of the right size.
|
||||
initialise(regValid);
|
||||
@ -74,14 +74,37 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an attempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::getBorderValue(void) const
|
||||
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
return m_tBorderValue;
|
||||
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
|
||||
|
||||
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
||||
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
||||
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
||||
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
||||
|
||||
return m_pData
|
||||
[
|
||||
iLocalXPos +
|
||||
iLocalYPos * this->getWidth() +
|
||||
iLocalZPos * this->getWidth() * this->getHeight()
|
||||
];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos) const
|
||||
{
|
||||
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -124,12 +147,59 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||
VoxelType RawVolume<VoxelType>::getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||
{
|
||||
m_tBorderValue = tBorder;
|
||||
switch(eWrapMode)
|
||||
{
|
||||
case WrapModes::Clamp:
|
||||
{
|
||||
//Perform clamping
|
||||
uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
|
||||
uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
|
||||
uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
|
||||
uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
|
||||
uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
|
||||
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
|
||||
|
||||
//Get the voxel value
|
||||
return getVoxel(uXPos, uYPos, uZPos);
|
||||
//No need to break as we've returned
|
||||
}
|
||||
case WrapModes::Border:
|
||||
{
|
||||
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
|
||||
{
|
||||
return getVoxel(uXPos, uYPos, uZPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tBorder;
|
||||
}
|
||||
//No need to break as we've returned
|
||||
}
|
||||
default:
|
||||
{
|
||||
//Should never happen
|
||||
assert(false);
|
||||
return VoxelType(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||
{
|
||||
return getVoxelWithWrapping(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -21,12 +21,12 @@ freely, subject to the following restrictions:
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#define BORDER_LOWX(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getX())
|
||||
#define BORDER_HIGHX(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getX())
|
||||
#define BORDER_LOWY(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getY())
|
||||
#define BORDER_HIGHY(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getY())
|
||||
#define BORDER_LOWZ(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getZ())
|
||||
#define BORDER_HIGHZ(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getZ())
|
||||
#define CAN_GO_NEG_X(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getX())
|
||||
#define CAN_GO_POS_X(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getX())
|
||||
#define CAN_GO_NEG_Y(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getY())
|
||||
#define CAN_GO_POS_Y(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getY())
|
||||
#define CAN_GO_NEG_Z(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getZ())
|
||||
#define CAN_GO_POS_Z(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getZ())
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
@ -34,9 +34,6 @@ namespace PolyVox
|
||||
RawVolume<VoxelType>::Sampler::Sampler(RawVolume<VoxelType>* volume)
|
||||
:BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >(volume)
|
||||
,mCurrentVoxel(0)
|
||||
,m_bIsCurrentPositionValidInX(false)
|
||||
,m_bIsCurrentPositionValidInY(false)
|
||||
,m_bIsCurrentPositionValidInZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -48,7 +45,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::getVoxel(void) const
|
||||
{
|
||||
return (m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ) ? *mCurrentVoxel : this->mVolume->getBorderValue();
|
||||
if(this->isCurrentPositionValid())
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getVoxelAt(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -60,31 +64,34 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||
{
|
||||
this->mXPosInVolume = xPos;
|
||||
this->mYPosInVolume = yPos;
|
||||
this->mZPosInVolume = zPos;
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >::setPosition(xPos, yPos, zPos);
|
||||
|
||||
const Vector3DInt32& v3dLowerCorner = this->mVolume->m_regValidRegion.getLowerCorner();
|
||||
int32_t iLocalXPos = xPos - v3dLowerCorner.getX();
|
||||
int32_t iLocalYPos = yPos - v3dLowerCorner.getY();
|
||||
int32_t iLocalZPos = zPos - v3dLowerCorner.getZ();
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid())
|
||||
{
|
||||
const Vector3DInt32& v3dLowerCorner = this->mVolume->m_regValidRegion.getLowerCorner();
|
||||
int32_t iLocalXPos = xPos - v3dLowerCorner.getX();
|
||||
int32_t iLocalYPos = yPos - v3dLowerCorner.getY();
|
||||
int32_t iLocalZPos = zPos - v3dLowerCorner.getZ();
|
||||
|
||||
const int32_t uVoxelIndex = iLocalXPos +
|
||||
iLocalYPos * this->mVolume->getWidth() +
|
||||
iLocalZPos * this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
const int32_t uVoxelIndex = iLocalXPos +
|
||||
iLocalYPos * this->mVolume->getWidth() +
|
||||
iLocalZPos * this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
|
||||
mCurrentVoxel = this->mVolume->m_pData + uVoxelIndex;
|
||||
|
||||
m_bIsCurrentPositionValidInX = this->mVolume->getEnclosingRegion().containsPointInX(xPos);
|
||||
m_bIsCurrentPositionValidInY = this->mVolume->getEnclosingRegion().containsPointInY(yPos);
|
||||
m_bIsCurrentPositionValidInZ = this->mVolume->getEnclosingRegion().containsPointInZ(zPos);
|
||||
mCurrentVoxel = this->mVolume->m_pData + uVoxelIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentVoxel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
bool RawVolume<VoxelType>::Sampler::setVoxel(VoxelType tValue)
|
||||
{
|
||||
//return m_bIsCurrentPositionValid ? *mCurrentVoxel : this->mVolume->getBorderValue();
|
||||
if(m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ)
|
||||
if(this->m_bIsCurrentPositionValidInX && this->m_bIsCurrentPositionValidInY && this->m_bIsCurrentPositionValidInZ)
|
||||
{
|
||||
*mCurrentVoxel = tValue;
|
||||
return true;
|
||||
@ -98,139 +105,211 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::movePositiveX(void)
|
||||
{
|
||||
this->mXPosInVolume++;
|
||||
++mCurrentVoxel;
|
||||
m_bIsCurrentPositionValidInX = this->mVolume->getEnclosingRegion().containsPointInX(this->mXPosInVolume);
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >::movePositiveX();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid() && bIsOldPositionValid )
|
||||
{
|
||||
++mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::movePositiveY(void)
|
||||
{
|
||||
this->mYPosInVolume++;
|
||||
mCurrentVoxel += this->mVolume->getWidth();
|
||||
m_bIsCurrentPositionValidInY = this->mVolume->getEnclosingRegion().containsPointInY(this->mYPosInVolume);
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >::movePositiveY();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid() && bIsOldPositionValid )
|
||||
{
|
||||
mCurrentVoxel += this->mVolume->getWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::movePositiveZ(void)
|
||||
{
|
||||
this->mZPosInVolume++;
|
||||
mCurrentVoxel += this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
m_bIsCurrentPositionValidInZ = this->mVolume->getEnclosingRegion().containsPointInZ(this->mZPosInVolume);
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >::movePositiveZ();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid() && bIsOldPositionValid )
|
||||
{
|
||||
mCurrentVoxel += this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::moveNegativeX(void)
|
||||
{
|
||||
this->mXPosInVolume--;
|
||||
--mCurrentVoxel;
|
||||
m_bIsCurrentPositionValidInX = this->mVolume->getEnclosingRegion().containsPointInX(this->mXPosInVolume);
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >::moveNegativeX();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid() && bIsOldPositionValid )
|
||||
{
|
||||
--mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::moveNegativeY(void)
|
||||
{
|
||||
this->mYPosInVolume--;
|
||||
mCurrentVoxel -= this->mVolume->getWidth();
|
||||
m_bIsCurrentPositionValidInY = this->mVolume->getEnclosingRegion().containsPointInY(this->mYPosInVolume);
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >::moveNegativeY();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid() && bIsOldPositionValid )
|
||||
{
|
||||
mCurrentVoxel -= this->mVolume->getWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::moveNegativeZ(void)
|
||||
{
|
||||
this->mZPosInVolume--;
|
||||
mCurrentVoxel -= this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
m_bIsCurrentPositionValidInZ = this->mVolume->getEnclosingRegion().containsPointInZ(this->mZPosInVolume);
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >::moveNegativeZ();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid() && bIsOldPositionValid )
|
||||
{
|
||||
mCurrentVoxel -= this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -238,87 +317,91 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWY(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
if((this->isCurrentPositionValid()))
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHY(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -326,97 +409,97 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
}
|
||||
|
||||
#undef BORDER_LOWX
|
||||
#undef BORDER_HIGHX
|
||||
#undef BORDER_LOWY
|
||||
#undef BORDER_HIGHY
|
||||
#undef BORDER_LOWZ
|
||||
#undef BORDER_HIGHZ
|
||||
#undef CAN_GO_NEG_X
|
||||
#undef CAN_GO_POS_X
|
||||
#undef CAN_GO_NEG_Y
|
||||
#undef CAN_GO_POS_Y
|
||||
#undef CAN_GO_NEG_Z
|
||||
#undef CAN_GO_POS_Z
|
||||
|
@ -30,21 +30,25 @@ freely, subject to the following restrictions:
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
Represents a part of a Volume.
|
||||
|
||||
Many operations in PolyVox are constrained to only part of a volume. For example, when running the surface extractors
|
||||
it is unlikely that you will want to run it on the whole volume at once, as this will give a very large mesh which may
|
||||
be too much to render. Instead you will probably want to run a surface extractor a number of times on different parts
|
||||
of the volume, there by giving a number of meshes which can be culled and rendered seperately.
|
||||
|
||||
The Region class is used to define these parts (regions) of the volume. Essentially it consists of an upper and lower
|
||||
bound which specify the range of voxels positions considered to be part of the region. Note that these bounds are
|
||||
<em>inclusive</em>. The class also provides functions for modifying the regions in a variety of ways.
|
||||
|
||||
\Note The dimensions of a region can be measured either in voxels or in cells. See the manual for more information
|
||||
about these definitions.
|
||||
*/
|
||||
/** Represents a part of a Volume.
|
||||
*
|
||||
* Many operations in PolyVox are constrained to only part of a volume. For example, when running the surface extractors
|
||||
* it is unlikely that you will want to run it on the whole volume at once, as this will give a very large mesh which may
|
||||
* be too much to render. Instead you will probably want to run a surface extractor a number of times on different parts
|
||||
* of the volume, there by giving a number of meshes which can be culled and rendered seperately.
|
||||
*
|
||||
* The Region class is used to define these parts (regions) of the volume. Essentially it consists of an upper and lower
|
||||
* bound which specify the range of voxels positions considered to be part of the region. Note that these bounds are
|
||||
* <em>inclusive</em>.
|
||||
*
|
||||
* As well as the expected set of getters and setters, this class also provide utility functions for increasing and decresing
|
||||
* the size of the Region, shifting the Region in 3D space, testing whether it contains a given position, enlarging it so that
|
||||
* it does contain a given position, croppng it to another Region, and various other utility functions.
|
||||
*
|
||||
* \Note The dimensions of a region can be measured either in voxels or in cells. See the manual for more information
|
||||
* about these definitions.
|
||||
*
|
||||
*/
|
||||
#ifdef SWIG
|
||||
class Region
|
||||
#else
|
||||
@ -53,74 +57,355 @@ namespace PolyVox
|
||||
{
|
||||
public:
|
||||
|
||||
/// A Region with the lower corner set as low as possible and the upper corner set as high as possible.
|
||||
static const Region MaxRegion;
|
||||
/// A Region with the lower corner set as high as possible and the upper corner set as low as possible.
|
||||
static const Region InvertedRegion;
|
||||
|
||||
/// Constructor
|
||||
Region();
|
||||
/// Constructor
|
||||
Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner);
|
||||
/// Constructor
|
||||
Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ);
|
||||
|
||||
///Equality Operator.
|
||||
/// Equality Operator.
|
||||
bool operator==(const Region& rhs) const;
|
||||
///Inequality Operator.
|
||||
/// Inequality Operator.
|
||||
bool operator!=(const Region& rhs) const;
|
||||
|
||||
const Vector3DInt32& getLowerCorner(void) const;
|
||||
const Vector3DInt32& getUpperCorner(void) const;
|
||||
/// Gets the 'x' position of the lower corner.
|
||||
int32_t getLowerX(void) const;
|
||||
/// Gets the 'y' position of the lower corner.
|
||||
int32_t getLowerY(void) const;
|
||||
/// Gets the 'z' position of the lower corner.
|
||||
int32_t getLowerZ(void) const;
|
||||
/// Gets the 'x' position of the upper corner.
|
||||
int32_t getUpperX(void) const;
|
||||
/// Gets the 'y' position of the upper corner.
|
||||
int32_t getUpperY(void) const;
|
||||
/// Gets the 'z' position of the upper corner.
|
||||
int32_t getUpperZ(void) const;
|
||||
|
||||
/// Gets the width of the region measured in voxels
|
||||
/// Gets the position of the lower corner.
|
||||
Vector3DInt32 getLowerCorner(void) const;
|
||||
/// Gets the position of the upper corner.
|
||||
Vector3DInt32 getUpperCorner(void) const;
|
||||
|
||||
/// Gets the width of the region measured in voxels.
|
||||
int32_t getWidthInVoxels(void) const;
|
||||
/// Gets the height of the region measured in voxels
|
||||
/// Gets the height of the region measured in voxels.
|
||||
int32_t getHeightInVoxels(void) const;
|
||||
/// Gets the depth of the region measured in voxels
|
||||
/// Gets the depth of the region measured in voxels.
|
||||
int32_t getDepthInVoxels(void) const;
|
||||
/// Gets the dimensions of the region measured in voxels
|
||||
/// Gets the dimensions of the region measured in voxels.
|
||||
Vector3DInt32 getDimensionsInVoxels(void) const;
|
||||
|
||||
/// Gets the width of the region measured in cells
|
||||
/// Gets the width of the region measured in cells.
|
||||
int32_t getWidthInCells(void) const;
|
||||
/// Gets the height of the region measured in cells
|
||||
/// Gets the height of the region measured in cells.
|
||||
int32_t getHeightInCells(void) const;
|
||||
/// Gets the depth of the region measured in cells
|
||||
/// Gets the depth of the region measured in cells.
|
||||
int32_t getDepthInCells(void) const;
|
||||
/// Gets the dimensions of the region measured in cells
|
||||
/// Gets the dimensions of the region measured in cells.
|
||||
Vector3DInt32 getDimensionsInCells(void) const;
|
||||
|
||||
/// Sets the 'x' position of the lower corner.
|
||||
void setLowerX(int32_t iX);
|
||||
/// Sets the 'y' position of the lower corner.
|
||||
void setLowerY(int32_t iY);
|
||||
/// Sets the 'z' position of the lower corner.
|
||||
void setLowerZ(int32_t iZ);
|
||||
/// Sets the 'x' position of the upper corner.
|
||||
void setUpperX(int32_t iX);
|
||||
/// Sets the 'y' position of the upper corner.
|
||||
void setUpperY(int32_t iY);
|
||||
/// Sets the 'z' position of the upper corner.
|
||||
void setUpperZ(int32_t iZ);
|
||||
|
||||
/// Sets the position of the lower corner.
|
||||
void setLowerCorner(const Vector3DInt32& v3dLowerCorner);
|
||||
/// Sets the position of the upper corner.
|
||||
void setUpperCorner(const Vector3DInt32& v3dUpperCorner);
|
||||
|
||||
/// Tests whether the given point is contained in this Region.
|
||||
bool containsPoint(float fX, float fY, float fZ, float boundary = 0.0f) const;
|
||||
/// Tests whether the given point is contained in this Region.
|
||||
bool containsPoint(const Vector3DFloat& pos, float boundary = 0.0f) const;
|
||||
/// Tests whether the given point is contained in this Region.
|
||||
bool containsPoint(int32_t iX, int32_t iY, int32_t iZ, uint8_t boundary = 0) const;
|
||||
/// Tests whether the given point is contained in this Region.
|
||||
bool containsPoint(const Vector3DInt32& pos, uint8_t boundary = 0) const;
|
||||
//FIXME - Don't like these. Make containsPoint take flags indicating which axes to check?
|
||||
/// Tests whether the given position is contained in the 'x' range of this Region.
|
||||
bool containsPointInX(float pos, float boundary = 0.0f) const;
|
||||
/// Tests whether the given position is contained in the 'x' range of this Region.
|
||||
bool containsPointInX(int32_t pos, uint8_t boundary = 0) const;
|
||||
/// Tests whether the given position is contained in the 'y' range of this Region.
|
||||
bool containsPointInY(float pos, float boundary = 0.0f) const;
|
||||
/// Tests whether the given position is contained in the 'y' range of this Region.
|
||||
bool containsPointInY(int32_t pos, uint8_t boundary = 0) const;
|
||||
/// Tests whether the given position is contained in the 'z' range of this Region.
|
||||
bool containsPointInZ(float pos, float boundary = 0.0f) const;
|
||||
/// Tests whether the given position is contained in the 'z' range of this Region.
|
||||
bool containsPointInZ(int32_t pos, uint8_t boundary = 0) const;
|
||||
|
||||
/// Enlarges the Region so that it contains the specified position.
|
||||
void accumulate(int32_t iX, int32_t iY, int32_t iZ);
|
||||
/// Enlarges the Region so that it contains the specified position.
|
||||
void accumulate(const Vector3DInt32& v3dPos);
|
||||
/// Enlarges the Region so that it contains the specified Region.
|
||||
void accumulate(const Region& reg);
|
||||
|
||||
/// Crops the extents of this Region accoring to another Region.
|
||||
void cropTo(const Region& other);
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED int32_t depth(void) const;
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED int32_t height(void) const;
|
||||
void shift(const Vector3DInt32& amount);
|
||||
void shiftLowerCorner(const Vector3DInt32& amount);
|
||||
void shiftUpperCorner(const Vector3DInt32& amount);
|
||||
//FIXME - Add dilate and erode functions?
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED Vector3DInt32 dimensions(void);
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED int32_t width(void) const;
|
||||
|
||||
/// Grows this region by the amount specified.
|
||||
void grow(int32_t iAmount);
|
||||
/// Grows this region by the amounts specified.
|
||||
void grow(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||
/// Grows this region by the amounts specified.
|
||||
void grow(const Vector3DInt32& v3dAmount);
|
||||
|
||||
/// Tests whether all components of the upper corner are at least
|
||||
/// as great as the corresponding components of the lower corner.
|
||||
bool isValid(void) const;
|
||||
|
||||
/// Moves the Region by the amount specified.
|
||||
void shift(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||
/// Moves the Region by the amount specified.
|
||||
void shift(const Vector3DInt32& v3dAmount);
|
||||
/// Moves the lower corner of the Region by the amount specified.
|
||||
void shiftLowerCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||
/// Moves the lower corner of the Region by the amount specified.
|
||||
void shiftLowerCorner(const Vector3DInt32& v3dAmount);
|
||||
/// Moves the upper corner of the Region by the amount specified.
|
||||
void shiftUpperCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||
/// Moves the upper corner of the Region by the amount specified.
|
||||
void shiftUpperCorner(const Vector3DInt32& v3dAmount);
|
||||
|
||||
/// Shrinks this region by the amount specified.
|
||||
void shrink(int32_t iAmount);
|
||||
/// Shrinks this region by the amounts specified.
|
||||
void shrink(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||
/// Shrinks this region by the amounts specified.
|
||||
void shrink(const Vector3DInt32& v3dAmount);
|
||||
|
||||
private:
|
||||
Vector3DInt32 m_v3dLowerCorner;
|
||||
Vector3DInt32 m_v3dUpperCorner;
|
||||
|
||||
//FIXME - This variable is unused, but without it the OpenGL example crashes in release mode
|
||||
//when the volume size is 128^3 and the level of detail is 2. Very strange, but consistant.
|
||||
//Presubablly some kind of alignment issue? It started after this class was changed to use
|
||||
//int16's rather than int32's. To be investigated.
|
||||
uint8_t dummy;
|
||||
int32_t m_iLowerX;
|
||||
int32_t m_iLowerY;
|
||||
int32_t m_iLowerZ;
|
||||
int32_t m_iUpperX;
|
||||
int32_t m_iUpperY;
|
||||
int32_t m_iUpperZ;
|
||||
};
|
||||
|
||||
// Functions to be inlined to to be in the header rather than the .cpp.
|
||||
// 'inline' keyword is used for the definition rather than the declaration.
|
||||
// See also http://www.parashift.com/c++-faq-lite/inline-functions.html
|
||||
|
||||
/**
|
||||
* \return The 'x' position of the lower corner.
|
||||
*/
|
||||
inline int32_t Region::getLowerX(void) const
|
||||
{
|
||||
return m_iLowerX;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The 'y' position of the lower corner.
|
||||
*/
|
||||
inline int32_t Region::getLowerY(void) const
|
||||
{
|
||||
return m_iLowerY;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The 'z' position of the lower corner.
|
||||
*/
|
||||
inline int32_t Region::getLowerZ(void) const
|
||||
{
|
||||
return m_iLowerZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The 'x' position of the upper corner.
|
||||
*/
|
||||
inline int32_t Region::getUpperX(void) const
|
||||
{
|
||||
return m_iUpperX;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The 'y' position of the upper corner.
|
||||
*/
|
||||
inline int32_t Region::getUpperY(void) const
|
||||
{
|
||||
return m_iUpperY;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The 'z' position of the upper corner.
|
||||
*/
|
||||
inline int32_t Region::getUpperZ(void) const
|
||||
{
|
||||
return m_iUpperZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The position of the lower corner.
|
||||
*/
|
||||
inline Vector3DInt32 Region::getLowerCorner(void) const
|
||||
{
|
||||
return Vector3DInt32(m_iLowerX, m_iLowerY, m_iLowerZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The position of the upper corner.
|
||||
*/
|
||||
inline Vector3DInt32 Region::getUpperCorner(void) const
|
||||
{
|
||||
return Vector3DInt32(m_iUpperX, m_iUpperY, m_iUpperZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The width of the region measured in voxels.
|
||||
* \sa getWidthInCells()
|
||||
*/
|
||||
inline int32_t Region::getWidthInVoxels(void) const
|
||||
{
|
||||
return getWidthInCells() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The height of the region measured in voxels.
|
||||
* \sa getHeightInCells()
|
||||
*/
|
||||
inline int32_t Region::getHeightInVoxels(void) const
|
||||
{
|
||||
return getHeightInCells() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The depth of the region measured in voxels.
|
||||
* \sa getDepthInCells()
|
||||
*/
|
||||
inline int32_t Region::getDepthInVoxels(void) const
|
||||
{
|
||||
return getDepthInCells() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The dimensions of the region measured in voxels.
|
||||
* \sa getDimensionsInCells()
|
||||
*/
|
||||
inline Vector3DInt32 Region::getDimensionsInVoxels(void) const
|
||||
{
|
||||
return getDimensionsInCells() + Vector3DInt32(1, 1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The width of the region measured in cells.
|
||||
* \sa getWidthInVoxels()
|
||||
*/
|
||||
inline int32_t Region::getWidthInCells(void) const
|
||||
{
|
||||
return m_iUpperX - m_iLowerX;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The height of the region measured in cells.
|
||||
* \sa getHeightInVoxels()
|
||||
*/
|
||||
inline int32_t Region::getHeightInCells(void) const
|
||||
{
|
||||
return m_iUpperY - m_iLowerY;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The depth of the region measured in cells.
|
||||
* \sa getDepthInVoxels()
|
||||
*/
|
||||
inline int32_t Region::getDepthInCells(void) const
|
||||
{
|
||||
return m_iUpperZ - m_iLowerZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The dimensions of the region measured in cells.
|
||||
* \sa getDimensionsInVoxels()
|
||||
*/
|
||||
inline Vector3DInt32 Region::getDimensionsInCells(void) const
|
||||
{
|
||||
return Vector3DInt32(getWidthInCells(), getHeightInCells(), getDepthInCells());
|
||||
}
|
||||
|
||||
/**
|
||||
* \param iX The new 'x' position of the lower corner.
|
||||
*/
|
||||
inline void Region::setLowerX(int32_t iX)
|
||||
{
|
||||
m_iLowerX = iX;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param iY The new 'y' position of the lower corner.
|
||||
*/
|
||||
inline void Region::setLowerY(int32_t iY)
|
||||
{
|
||||
m_iLowerY = iY;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param iZ The new 'z' position of the lower corner.
|
||||
*/
|
||||
inline void Region::setLowerZ(int32_t iZ)
|
||||
{
|
||||
m_iLowerZ = iZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param iX The new 'x' position of the upper corner.
|
||||
*/
|
||||
inline void Region::setUpperX(int32_t iX)
|
||||
{
|
||||
m_iUpperX = iX;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param iY The new 'y' position of the upper corner.
|
||||
*/
|
||||
inline void Region::setUpperY(int32_t iY)
|
||||
{
|
||||
m_iUpperY = iY;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param iZ The new 'z' position of the upper corner.
|
||||
*/
|
||||
inline void Region::setUpperZ(int32_t iZ)
|
||||
{
|
||||
m_iUpperZ = iZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param v3dLowerCorner The new position of the lower corner.
|
||||
*/
|
||||
inline void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner)
|
||||
{
|
||||
m_iLowerX = v3dLowerCorner.getX();
|
||||
m_iLowerY = v3dLowerCorner.getY();
|
||||
m_iLowerZ = v3dLowerCorner.getZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* \param v3dUpperCorner The new position of the upper corner.
|
||||
*/
|
||||
inline void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner)
|
||||
{
|
||||
m_iUpperX = v3dUpperCorner.getX();
|
||||
m_iUpperY = v3dUpperCorner.getY();
|
||||
m_iUpperZ = v3dUpperCorner.getZ();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,46 +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_SimpleInterface_H__
|
||||
#define __PolyVox_SimpleInterface_H__
|
||||
|
||||
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||
#include "PolyVoxCore/SimpleVolume.h"
|
||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
//The PolyVox simple interface only exposes one voxel type and one volume type. But if you like you can
|
||||
//adjust these typedefs and rebuild the library in order to modify which one volume and voxel is exposed.
|
||||
typedef SimpleVolume<MaterialDensityPair88> Volume;
|
||||
typedef SurfaceMesh<PositionMaterialNormal> Mesh;
|
||||
|
||||
/// \deprecated
|
||||
POLYVOX_DEPRECATED void extractCubicMesh(Volume& volume, const Region& region, Mesh& resultMesh);
|
||||
/// \deprecated
|
||||
POLYVOX_DEPRECATED void extractSmoothMesh(Volume& volume, const Region& region, Mesh& resultMesh);
|
||||
|
||||
}
|
||||
|
||||
#endif //__PolyVox_SimpleInterface_H__
|
@ -87,9 +87,8 @@ namespace PolyVox
|
||||
Sampler(SimpleVolume<VoxelType>* volume);
|
||||
~Sampler();
|
||||
|
||||
Sampler& operator=(const Sampler& rhs);
|
||||
|
||||
VoxelType getSubSampledVoxel(uint8_t uLevel) const;
|
||||
/// \deprecated
|
||||
POLYVOX_DEPRECATED VoxelType getSubSampledVoxel(uint8_t uLevel) const;
|
||||
/// Get the value of the current voxel
|
||||
inline VoxelType getVoxel(void) const;
|
||||
|
||||
@ -157,15 +156,19 @@ namespace PolyVox
|
||||
/// Destructor
|
||||
~SimpleVolume();
|
||||
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxel(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
|
||||
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
@ -189,12 +192,6 @@ namespace PolyVox
|
||||
//The block data
|
||||
Block* m_pBlocks;
|
||||
|
||||
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
||||
//block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a
|
||||
//good chance we'll often hit it anyway. It's a chunk of homogenous data (rather than a single value) so that
|
||||
//the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume.
|
||||
VoxelType* m_pUncompressedBorderData;
|
||||
|
||||
//The size of the volume in vlocks
|
||||
Region m_regValidRegionInBlocks;
|
||||
|
||||
|
@ -56,7 +56,6 @@ namespace PolyVox
|
||||
SimpleVolume<VoxelType>::~SimpleVolume()
|
||||
{
|
||||
delete[] m_pBlocks;
|
||||
delete[] m_pUncompressedBorderData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -73,14 +72,37 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an attempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::getBorderValue(void) const
|
||||
VoxelType SimpleVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
return *m_pUncompressedBorderData;
|
||||
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
|
||||
|
||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t xOffset = static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos) const
|
||||
{
|
||||
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -108,7 +130,7 @@ namespace PolyVox
|
||||
}
|
||||
else
|
||||
{
|
||||
return getBorderValue();
|
||||
return this->getBorderValue();
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,14 +145,59 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||
VoxelType SimpleVolume<VoxelType>::getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||
{
|
||||
/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
|
||||
return pUncompressedBorderBlock->fill(tBorder);*/
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, tBorder);
|
||||
switch(eWrapMode)
|
||||
{
|
||||
case WrapModes::Clamp:
|
||||
{
|
||||
//Perform clamping
|
||||
uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
|
||||
uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
|
||||
uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
|
||||
uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
|
||||
uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
|
||||
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
|
||||
|
||||
//Get the voxel value
|
||||
return getVoxel(uXPos, uYPos, uZPos);
|
||||
//No need to break as we've returned
|
||||
}
|
||||
case WrapModes::Border:
|
||||
{
|
||||
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
|
||||
{
|
||||
return getVoxel(uXPos, uYPos, uZPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tBorder;
|
||||
}
|
||||
//No need to break as we've returned
|
||||
}
|
||||
default:
|
||||
{
|
||||
//Should never happen
|
||||
assert(false);
|
||||
return VoxelType(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||
{
|
||||
return getVoxelWithWrapping(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -197,18 +264,19 @@ namespace PolyVox
|
||||
throw std::invalid_argument("Block side length must be a power of two.");
|
||||
}
|
||||
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_uNoOfVoxelsPerBlock = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength;
|
||||
m_pUncompressedBorderData = 0;
|
||||
|
||||
this->m_regValidRegion = regValidRegion;
|
||||
|
||||
m_regValidRegionInBlocks.setLowerCorner(this->m_regValidRegion.getLowerCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
|
||||
//Compute the block side length
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
||||
m_uNoOfVoxelsPerBlock = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength;
|
||||
|
||||
m_regValidRegionInBlocks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setLowerY(this->m_regValidRegion.getLowerY() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setLowerZ(this->m_regValidRegion.getLowerZ() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperX(this->m_regValidRegion.getUpperX() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperY(this->m_regValidRegion.getUpperY() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperZ(this->m_regValidRegion.getUpperZ() >> m_uBlockSideLengthPower);
|
||||
|
||||
//Compute the size of the volume in blocks (and note +1 at the end)
|
||||
m_uWidthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getX() - m_regValidRegionInBlocks.getLowerCorner().getX() + 1;
|
||||
@ -223,10 +291,6 @@ namespace PolyVox
|
||||
m_pBlocks[i].initialise(m_uBlockSideLength);
|
||||
}
|
||||
|
||||
//Create the border block
|
||||
m_pUncompressedBorderData = new VoxelType[m_uNoOfVoxelsPerBlock];
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, VoxelType());
|
||||
|
||||
//Other properties we might find useful later
|
||||
this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
@ -242,6 +306,10 @@ namespace PolyVox
|
||||
uBlockY -= m_regValidRegionInBlocks.getLowerCorner().getY();
|
||||
uBlockZ -= m_regValidRegionInBlocks.getLowerCorner().getZ();
|
||||
|
||||
assert(uBlockX >= 0);
|
||||
assert(uBlockY >= 0);
|
||||
assert(uBlockZ >= 0);
|
||||
|
||||
//Compute the block index
|
||||
uint32_t uBlockIndex =
|
||||
uBlockX +
|
||||
@ -264,8 +332,8 @@ namespace PolyVox
|
||||
|
||||
uint32_t uSizeOfBlockInBytes = m_uNoOfVoxelsPerBlock * sizeof(VoxelType);
|
||||
|
||||
//Memory used by the blocks ( + 1 is for border)
|
||||
uSizeInBytes += uSizeOfBlockInBytes * (m_uNoOfBlocksInVolume + 1);
|
||||
//Memory used by the blocks
|
||||
uSizeInBytes += uSizeOfBlockInBytes * (m_uNoOfBlocksInVolume);
|
||||
|
||||
return uSizeInBytes;
|
||||
}
|
||||
|
@ -21,10 +21,12 @@ freely, subject to the following restrictions:
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#define BORDER_LOW(x) ((( x >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != x)
|
||||
#define BORDER_HIGH(x) ((( (x+1) >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != (x+1))
|
||||
//#define BORDER_LOW(x) (( x % this->mVolume->m_uBlockSideLength) != 0)
|
||||
//#define BORDER_HIGH(x) (( x % this->mVolume->m_uBlockSideLength) != this->mVolume->m_uBlockSideLength - 1)
|
||||
#define CAN_GO_NEG_X(val) ((val > this->mVolume->getEnclosingRegion().getLowerCorner().getX()) && (val % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_POS_X(val) ((val < this->mVolume->getEnclosingRegion().getUpperCorner().getX()) && ((val + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_NEG_Y(val) ((val > this->mVolume->getEnclosingRegion().getLowerCorner().getY()) && (val % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_POS_Y(val) ((val < this->mVolume->getEnclosingRegion().getUpperCorner().getY()) && ((val + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_NEG_Z(val) ((val > this->mVolume->getEnclosingRegion().getLowerCorner().getZ()) && (val % this->mVolume->m_uBlockSideLength != 0))
|
||||
#define CAN_GO_POS_Z(val) ((val < this->mVolume->getEnclosingRegion().getUpperCorner().getZ()) && ((val + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
@ -42,21 +44,6 @@ namespace PolyVox
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
typename SimpleVolume<VoxelType>::Sampler& SimpleVolume<VoxelType>::Sampler::operator=(const typename SimpleVolume<VoxelType>::Sampler& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
this->mVolume = rhs.mVolume;
|
||||
this->mXPosInVolume = rhs.mXPosInVolume;
|
||||
this->mYPosInVolume = rhs.mYPosInVolume;
|
||||
this->mZPosInVolume = rhs.mZPosInVolume;
|
||||
mCurrentVoxel = rhs.mCurrentVoxel;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::getSubSampledVoxel(uint8_t uLevel) const
|
||||
{
|
||||
@ -101,7 +88,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::getVoxel(void) const
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
if(this->isCurrentPositionValid())
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getVoxelAt(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,31 +115,31 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||
{
|
||||
this->mXPosInVolume = xPos;
|
||||
this->mYPosInVolume = yPos;
|
||||
this->mZPosInVolume = zPos;
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >::setPosition(xPos, yPos, zPos);
|
||||
|
||||
const int32_t uXBlock = this->mXPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uYBlock = this->mYPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uZBlock = this->mZPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t uXPosInBlock = static_cast<uint16_t>(this->mXPosInVolume - (uXBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uYPosInBlock = static_cast<uint16_t>(this->mYPosInVolume - (uYBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uZPosInBlock = static_cast<uint16_t>(this->mZPosInVolume - (uZBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
|
||||
const uint32_t uVoxelIndexInBlock = uXPosInBlock +
|
||||
uYPosInBlock * this->mVolume->m_uBlockSideLength +
|
||||
uZPosInBlock * this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
|
||||
if(this->mVolume->m_regValidRegionInBlocks.containsPoint(Vector3DInt32(uXBlock, uYBlock, uZBlock)))
|
||||
// Then we update the voxel pointer
|
||||
if(this->isCurrentPositionValid())
|
||||
{
|
||||
const int32_t uXBlock = this->mXPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uYBlock = this->mYPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uZBlock = this->mZPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t uXPosInBlock = static_cast<uint16_t>(this->mXPosInVolume - (uXBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uYPosInBlock = static_cast<uint16_t>(this->mYPosInVolume - (uYBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uZPosInBlock = static_cast<uint16_t>(this->mZPosInVolume - (uZBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
|
||||
const uint32_t uVoxelIndexInBlock = uXPosInBlock +
|
||||
uYPosInBlock * this->mVolume->m_uBlockSideLength +
|
||||
uZPosInBlock * this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
|
||||
Block* pUncompressedCurrentBlock = this->mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock);
|
||||
|
||||
mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentVoxel = this->mVolume->m_pUncompressedBorderData + uVoxelIndexInBlock;
|
||||
mCurrentVoxel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,10 +155,7 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
bool SimpleVolume<VoxelType>::Sampler::setVoxel(VoxelType tValue)
|
||||
{
|
||||
VoxelType* pBorderDataEndPlusOne = this->mVolume->m_pUncompressedBorderData + this->mVolume->m_uNoOfVoxelsPerBlock;
|
||||
|
||||
//Make sure we're not trying to write to the border data
|
||||
if((mCurrentVoxel < this->mVolume->m_pUncompressedBorderData) || (mCurrentVoxel >= pBorderDataEndPlusOne))
|
||||
if(this->m_bIsCurrentPositionValidInX && this->m_bIsCurrentPositionValidInY && this->m_bIsCurrentPositionValidInZ)
|
||||
{
|
||||
*mCurrentVoxel = tValue;
|
||||
return true;
|
||||
@ -178,8 +169,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::movePositiveX(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mXPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >::movePositiveX();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mXPosInVolume) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
++mCurrentVoxel;
|
||||
@ -194,8 +191,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::movePositiveY(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mYPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >::movePositiveY();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mYPosInVolume) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength;
|
||||
@ -210,8 +213,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::movePositiveZ(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mZPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >::movePositiveZ();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mZPosInVolume) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
@ -226,8 +235,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::moveNegativeX(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mXPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >::moveNegativeX();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mXPosInVolume + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
--mCurrentVoxel;
|
||||
@ -242,8 +257,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::moveNegativeY(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mYPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >::moveNegativeY();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mYPosInVolume + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength;
|
||||
@ -258,8 +279,14 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::moveNegativeZ(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mZPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
// We'll need this in a moment...
|
||||
bool bIsOldPositionValid = this->isCurrentPositionValid();
|
||||
|
||||
// Base version updates position and validity flags.
|
||||
BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >::moveNegativeZ();
|
||||
|
||||
// Then we update the voxel pointer
|
||||
if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mZPosInVolume + 1) % this->mVolume->m_uBlockSideLength != 0))
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
@ -274,91 +301,91 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -366,87 +393,91 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
if((this->isCurrentPositionValid()))
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -454,93 +485,97 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder);
|
||||
}
|
||||
}
|
||||
|
||||
#undef BORDER_LOW
|
||||
#undef BORDER_HIGH
|
||||
#undef CAN_GO_NEG_X
|
||||
#undef CAN_GO_POS_X
|
||||
#undef CAN_GO_NEG_Y
|
||||
#undef CAN_GO_POS_Y
|
||||
#undef CAN_GO_NEG_Z
|
||||
#undef CAN_GO_POS_Z
|
||||
|
@ -36,192 +36,193 @@ freely, subject to the following restrictions:
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
Represents a vector in space.
|
||||
|
||||
This Vector class is templated on both size and data type. It is designed to be
|
||||
generic but so far had only been tested with vectors of size 2 and 3. Also note
|
||||
that some of the operations do not make sense with integer types, for example it
|
||||
does not make conceptual sense to try and normalise an integer Vector.
|
||||
|
||||
The elements of the Vector are accessed via the overloaded () operator which takes
|
||||
an index indicating the element to fetch. They are set using the set() function which
|
||||
takes an index indicating the element to set and a new value for that element. For
|
||||
convienience, the functions getX(), setX(), getY(), setY(), getZ(), setZ(), getw() and setW()
|
||||
do the same thing for the first 4 elements of the Vector.
|
||||
|
||||
A variety of overloaded operators are also provided for comparison and arithmetic
|
||||
operations. For most of these arithmetic operators only the unary versions are
|
||||
documented below - however often binary versions are also generated by std::operators.
|
||||
|
||||
Lastly, note that for convienience a set of typedefs are included for 2 and 3 dimensional
|
||||
vectors with type float, double, int32_t, and uint32_t. They are used as follows:
|
||||
|
||||
\code
|
||||
Vector2DInt4 test(1,2); //Declares a 2 dimensional Vector of type int4.
|
||||
\endcode
|
||||
*/
|
||||
* Represents a vector in space.
|
||||
*
|
||||
* This is a generl purpose vector class designed to represent both positions and directions. It is templatised
|
||||
* on both size and data type but note that some of the operations do not make sense with integer types. For
|
||||
* example it does not make conceptual sense to try and normalise an integer Vector.
|
||||
*
|
||||
* Every Vector must have at at least two elements, and the first four elements of any vector are known as the
|
||||
* X, Y, Z and W elements. Note that W is last even though it comes before X in the alphabet. These elements can
|
||||
* be accessed through getX(), setX(), getY(), setY(), getZ(), setZ(), getW() and setW(), while other elements
|
||||
* can be accessed through getElemen() and setElement().
|
||||
*
|
||||
* This class includes a number of common mathematical operations (addition, subtraction, etc) as well as vector
|
||||
* specific operations such as the dot and cross products. Note that this class is also templatised on an
|
||||
* OperationType which is used for many internal calculations and some results. For example, the square of a
|
||||
* vector's length will always be an integer if all the elements are integers, but the value might be outside
|
||||
* that which can be represented by the StorageType. You don't need to worry about this as long as you are using
|
||||
* the built in typedefs for common configurations.
|
||||
*
|
||||
* Typedefs are provided for 2, 3 and 4 dimensional vector with int8_t, uint8_t, int16_t, uint6_t, int32_t,
|
||||
* uint32_t, float and double types. These typedefs are used as follows:
|
||||
*
|
||||
* \code
|
||||
* Vector2DInt32 test(1,2); //Declares a 2 dimensional Vector of type int32_t.
|
||||
* \endcode
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
///Constructor
|
||||
/// Constructor
|
||||
Vector(void);
|
||||
///Constructor.
|
||||
/// Constructor.
|
||||
Vector(StorageType tFillValue);
|
||||
///Constructor.
|
||||
/// Constructor.
|
||||
Vector(StorageType x, StorageType y);
|
||||
///Constructor.
|
||||
/// Constructor.
|
||||
Vector(StorageType x, StorageType y, StorageType z);
|
||||
///Constructor.
|
||||
/// Constructor.
|
||||
Vector(StorageType x, StorageType y, StorageType z, StorageType w);
|
||||
///Copy Constructor.
|
||||
/// Copy Constructor.
|
||||
Vector(const Vector<Size,StorageType,OperationType>& vector);
|
||||
///Copy Constructor which performs casting.
|
||||
/// Copy Constructor which performs casting.
|
||||
template <typename CastType> explicit Vector(const Vector<Size,CastType>& vector);
|
||||
///Destructor.
|
||||
/// Destructor.
|
||||
~Vector(void);
|
||||
|
||||
///Assignment Operator.
|
||||
/// Assignment Operator.
|
||||
Vector<Size,StorageType,OperationType>& operator=(const Vector<Size,StorageType,OperationType>& rhs);
|
||||
///Equality Operator.
|
||||
/// Equality Operator.
|
||||
bool operator==(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||
///Inequality Operator.
|
||||
/// Inequality Operator.
|
||||
bool operator!=(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||
///Comparison Operator.
|
||||
bool operator<(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||
///Addition and Assignment Operator.
|
||||
/// Comparison Operator.
|
||||
POLYVOX_DEPRECATED bool operator<(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||
/// Addition and Assignment Operator.
|
||||
Vector<Size,StorageType,OperationType>& operator+=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||
///Subtraction and Assignment Operator.
|
||||
/// Subtraction and Assignment Operator.
|
||||
Vector<Size,StorageType,OperationType>& operator-=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||
///Multiplication and Assignment Operator.
|
||||
/// Multiplication and Assignment Operator.
|
||||
Vector<Size,StorageType,OperationType>& operator*=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||
///Division and Assignment Operator.
|
||||
/// Division and Assignment Operator.
|
||||
Vector<Size,StorageType,OperationType>& operator/=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||
///Multiplication and Assignment Operator.
|
||||
/// Multiplication and Assignment Operator.
|
||||
Vector<Size,StorageType,OperationType>& operator*=(const StorageType& rhs);
|
||||
///Division and Assignment Operator.
|
||||
/// Division and Assignment Operator.
|
||||
Vector<Size,StorageType,OperationType>& operator/=(const StorageType& rhs);
|
||||
|
||||
///Element Access.
|
||||
/// Element Access.
|
||||
StorageType getElement(uint32_t index) const;
|
||||
///Get the x component of the vector.
|
||||
/// Get the x component of the vector.
|
||||
StorageType getX(void) const;
|
||||
///Get the y component of the vector.
|
||||
/// Get the y component of the vector.
|
||||
StorageType getY(void) const;
|
||||
///Get the z component of the vector.
|
||||
/// Get the z component of the vector.
|
||||
StorageType getZ(void) const;
|
||||
///Get the w component of the vector.
|
||||
/// Get the w component of the vector.
|
||||
StorageType getW(void) const;
|
||||
|
||||
///Element Access.
|
||||
/// Element Access.
|
||||
void setElement(uint32_t index, StorageType tValue);
|
||||
///Element Access.
|
||||
/// Element Access.
|
||||
void setElements(StorageType x, StorageType y);
|
||||
///Element Access.
|
||||
/// Element Access.
|
||||
void setElements(StorageType x, StorageType y, StorageType z);
|
||||
///Element Access.
|
||||
/// Element Access.
|
||||
void setElements(StorageType x, StorageType y, StorageType z, StorageType w);
|
||||
///Set the x component of the vector.
|
||||
/// Set the x component of the vector.
|
||||
void setX(StorageType tX);
|
||||
///Set the y component of the vector.
|
||||
/// Set the y component of the vector.
|
||||
void setY(StorageType tY);
|
||||
///Set the z component of the vector.
|
||||
/// Set the z component of the vector.
|
||||
void setZ(StorageType tZ);
|
||||
///Set the w component of the vector.
|
||||
/// Set the w component of the vector.
|
||||
void setW(StorageType tW);
|
||||
|
||||
///Get the length of the vector.
|
||||
double length(void) const;
|
||||
///Get the squared length of the vector.
|
||||
double lengthSquared(void) const;
|
||||
///Find the angle between this vector and that which is passed as a parameter.
|
||||
double angleTo(const Vector<Size,StorageType,OperationType>& vector) const;
|
||||
///Find the cross product between this vector and the vector passed as a parameter.
|
||||
/// Get the length of the vector.
|
||||
float length(void) const;
|
||||
/// Get the squared length of the vector.
|
||||
OperationType lengthSquared(void) const;
|
||||
/// Find the angle between this vector and that which is passed as a parameter.
|
||||
float angleTo(const Vector<Size,StorageType,OperationType>& vector) const;
|
||||
/// Find the cross product between this vector and the vector passed as a parameter.
|
||||
Vector<Size,StorageType,OperationType> cross(const Vector<Size,StorageType,OperationType>& vector) const;
|
||||
///Find the dot product between this vector and the vector passed as a parameter.
|
||||
StorageType dot(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||
///Normalise the vector.
|
||||
/// Find the dot product between this vector and the vector passed as a parameter.
|
||||
OperationType dot(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||
/// Normalise the vector.
|
||||
void normalise(void);
|
||||
|
||||
private:
|
||||
//Values for the vector
|
||||
// Values for the vector
|
||||
StorageType m_tElements[Size];
|
||||
};
|
||||
|
||||
//Non-member overloaded operators.
|
||||
///Addition operator.
|
||||
// Non-member overloaded operators.
|
||||
/// Addition operator.
|
||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator+(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||
///Subtraction operator.
|
||||
/// Subtraction operator.
|
||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator-(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||
///Multiplication operator.
|
||||
/// Multiplication operator.
|
||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||
///Division operator.
|
||||
/// Division operator.
|
||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||
///Multiplication operator.
|
||||
/// Multiplication operator.
|
||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs);
|
||||
///Division operator.
|
||||
/// Division operator.
|
||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs);
|
||||
///Stream insertion operator.
|
||||
/// Stream insertion operator.
|
||||
template <uint32_t Size, typename StorageType,typename OperationType>
|
||||
std::ostream& operator<<(std::ostream& os, const Vector<Size,StorageType,OperationType>& vector);
|
||||
|
||||
|
||||
//Some handy typedefs
|
||||
|
||||
///A 2D Vector of floats.
|
||||
/// A 2D Vector of floats.
|
||||
typedef Vector<2,float,float> Vector2DFloat;
|
||||
///A 2D Vector of doubles.
|
||||
/// A 2D Vector of doubles.
|
||||
typedef Vector<2,double,double> Vector2DDouble;
|
||||
///A 2D Vector of signed 8-bit values.
|
||||
/// A 2D Vector of signed 8-bit values.
|
||||
typedef Vector<2,int8_t,int32_t> Vector2DInt8;
|
||||
///A 2D Vector of unsigned 8-bit values.
|
||||
/// A 2D Vector of unsigned 8-bit values.
|
||||
typedef Vector<2,uint8_t,int32_t> Vector2DUint8;
|
||||
///A 2D Vector of signed 16-bit values.
|
||||
/// A 2D Vector of signed 16-bit values.
|
||||
typedef Vector<2,int16_t,int32_t> Vector2DInt16;
|
||||
///A 2D Vector of unsigned 16-bit values.
|
||||
/// A 2D Vector of unsigned 16-bit values.
|
||||
typedef Vector<2,uint16_t,int32_t> Vector2DUint16;
|
||||
///A 2D Vector of signed 32-bit values.
|
||||
/// A 2D Vector of signed 32-bit values.
|
||||
typedef Vector<2,int32_t,int32_t> Vector2DInt32;
|
||||
///A 2D Vector of unsigned 32-bit values.
|
||||
/// A 2D Vector of unsigned 32-bit values.
|
||||
typedef Vector<2,uint32_t,int32_t> Vector2DUint32;
|
||||
|
||||
///A 3D Vector of floats.
|
||||
/// A 3D Vector of floats.
|
||||
typedef Vector<3,float,float> Vector3DFloat;
|
||||
///A 3D Vector of doubles.
|
||||
/// A 3D Vector of doubles.
|
||||
typedef Vector<3,double,double> Vector3DDouble;
|
||||
///A 3D Vector of signed 8-bit values.
|
||||
/// A 3D Vector of signed 8-bit values.
|
||||
typedef Vector<3,int8_t,int32_t> Vector3DInt8;
|
||||
///A 3D Vector of unsigned 8-bit values.
|
||||
/// A 3D Vector of unsigned 8-bit values.
|
||||
typedef Vector<3,uint8_t,int32_t> Vector3DUint8;
|
||||
///A 3D Vector of signed 16-bit values.
|
||||
/// A 3D Vector of signed 16-bit values.
|
||||
typedef Vector<3,int16_t,int32_t> Vector3DInt16;
|
||||
///A 3D Vector of unsigned 16-bit values.
|
||||
/// A 3D Vector of unsigned 16-bit values.
|
||||
typedef Vector<3,uint16_t,int32_t> Vector3DUint16;
|
||||
///A 3D Vector of signed 32-bit values.
|
||||
/// A 3D Vector of signed 32-bit values.
|
||||
typedef Vector<3,int32_t,int32_t> Vector3DInt32;
|
||||
///A 3D Vector of unsigned 32-bit values.
|
||||
/// A 3D Vector of unsigned 32-bit values.
|
||||
typedef Vector<3,uint32_t,int32_t> Vector3DUint32;
|
||||
|
||||
///A 4D Vector of floats.
|
||||
/// A 4D Vector of floats.
|
||||
typedef Vector<4,float,float> Vector4DFloat;
|
||||
///A 4D Vector of doubles.
|
||||
/// A 4D Vector of doubles.
|
||||
typedef Vector<4,double,double> Vector4DDouble;
|
||||
///A 4D Vector of signed 8-bit values.
|
||||
/// A 4D Vector of signed 8-bit values.
|
||||
typedef Vector<4,int8_t,int32_t> Vector4DInt8;
|
||||
///A 4D Vector of unsigned 8-bit values.
|
||||
/// A 4D Vector of unsigned 8-bit values.
|
||||
typedef Vector<4,uint8_t,int32_t> Vector4DUint8;
|
||||
///A 4D Vector of signed 16-bit values.
|
||||
/// A 4D Vector of signed 16-bit values.
|
||||
typedef Vector<4,int16_t,int32_t> Vector4DInt16;
|
||||
///A 4D Vector of unsigned 16-bit values.
|
||||
/// A 4D Vector of unsigned 16-bit values.
|
||||
typedef Vector<4,uint16_t,int32_t> Vector4DUint16;
|
||||
///A 4D Vector of signed 32-bit values.
|
||||
/// A 4D Vector of signed 32-bit values.
|
||||
typedef Vector<4,int32_t,int32_t> Vector4DInt32;
|
||||
///A 4D Vector of unsigned 32-bit values.
|
||||
/// A 4D Vector of unsigned 32-bit values.
|
||||
typedef Vector<4,uint32_t,int32_t> Vector4DUint32;
|
||||
|
||||
|
||||
|
@ -25,17 +25,17 @@ namespace PolyVox
|
||||
{
|
||||
//-------------------------- Constructors, etc ---------------------------------
|
||||
/**
|
||||
Creates a Vector object but does not initialise it.
|
||||
*/
|
||||
* Creates a Vector object but does not initialise it.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
Vector<Size, StorageType, OperationType>::Vector(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a Vector object and initialises it with given values.
|
||||
\param x x component to set.
|
||||
*/
|
||||
* Creates a Vector object and initialises all components with the given value.
|
||||
* \param tFillValue The value to write to every component.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType>::Vector(StorageType tFillValue)
|
||||
{
|
||||
@ -46,10 +46,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a Vector object and initialises it with given values.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
*/
|
||||
* Creates a Vector object and initialises it with given values.
|
||||
* \param x The X component to set.
|
||||
* \param y The Y component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y)
|
||||
{
|
||||
@ -62,11 +62,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a Vector3D object and initialises it with given values.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
*/
|
||||
* Creates a Vector3D object and initialises it with given values.
|
||||
* \param x The X component to set.
|
||||
* \param y The Y component to set.
|
||||
* \param z the Z component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z)
|
||||
{
|
||||
@ -81,12 +81,12 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a Vector3D object and initialises it with given values.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
\param w w component to set.
|
||||
*/
|
||||
* Creates a Vector3D object and initialises it with given values.
|
||||
* \param x The X component to set.
|
||||
* \param y The Y component to set.
|
||||
* \param z The Z component to set.
|
||||
* \param w The W component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z, StorageType w)
|
||||
{
|
||||
@ -101,9 +101,9 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Copy constructor builds object based on object passed as parameter.
|
||||
\param vector A reference to the Vector to be copied.
|
||||
*/
|
||||
* Copy constructor builds object based on object passed as parameter.
|
||||
* \param vector A reference to the Vector to be copied.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
Vector<Size, StorageType, OperationType>::Vector(const Vector<Size, StorageType, OperationType>& vector)
|
||||
{
|
||||
@ -111,14 +111,14 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
This copy constructor allows casting between vectors with different data types.
|
||||
It is now possible to use code such as:
|
||||
|
||||
Vector3DDouble v3dDouble(1.0,2.0,3.0);
|
||||
Vector3DFloat v3dFloat = static_cast<Vector3DFloat>(v3dDouble); //Casting
|
||||
|
||||
\param vector A reference to the Vector to be copied.
|
||||
*/
|
||||
* This copy constructor allows casting between vectors with different data types.
|
||||
* It makes it possible to use code such as:
|
||||
*
|
||||
* Vector3DDouble v3dDouble(1.0,2.0,3.0);
|
||||
* Vector3DFloat v3dFloat = static_cast<Vector3DFloat>(v3dDouble); //Casting
|
||||
*
|
||||
* \param vector A reference to the Vector to be copied.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
template <typename CastType>
|
||||
Vector<Size, StorageType, OperationType>::Vector(const Vector<Size, CastType>& vector)
|
||||
@ -130,8 +130,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Destroys the Vector.
|
||||
*/
|
||||
* Destroys the Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
Vector<Size, StorageType, OperationType>::~Vector(void)
|
||||
{
|
||||
@ -146,10 +146,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Assignment operator copies each element of first Vector to the second.
|
||||
\param rhs Vector to assign to.
|
||||
\return A reference to the result to allow chaining.
|
||||
*/
|
||||
* Assignment operator copies each element of first Vector to the second.
|
||||
* \param rhs Vector to assign to.
|
||||
* \return A reference to the result to allow chaining.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
Vector<Size, StorageType, OperationType>& Vector<Size, StorageType, OperationType>::operator=(const Vector<Size, StorageType, OperationType>& rhs)
|
||||
{
|
||||
@ -162,11 +162,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Vectors are equal.
|
||||
\param rhs The Vector to compare to.
|
||||
\return true if the Vectors match.
|
||||
\see operator!=
|
||||
*/
|
||||
* Checks whether two Vectors are equal.
|
||||
* \param rhs The Vector to compare to.
|
||||
* \return true if the Vectors match.
|
||||
* \see operator!=
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline bool Vector<Size, StorageType, OperationType>::operator==(const Vector<Size, StorageType, OperationType> &rhs) const
|
||||
{
|
||||
@ -183,11 +183,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Vectors are not equal.
|
||||
\param rhs The Vector to compare to.
|
||||
\return true if the Vectors do not match.
|
||||
\see operator==
|
||||
*/
|
||||
* Checks whether two Vectors are not equal.
|
||||
* \param rhs The Vector to compare to.
|
||||
* \return true if the Vectors do not match.
|
||||
* \see operator==
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline bool Vector<Size, StorageType, OperationType>::operator!=(const Vector<Size, StorageType, OperationType> &rhs) const
|
||||
{
|
||||
@ -195,12 +195,14 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether this vector is less than the parameter. The metric is
|
||||
meaningless but it allows Vectors to me used as key in sdt::map, etc.
|
||||
\param rhs The Vector to compare to.
|
||||
\return true if this is less than the parameter
|
||||
\see operator!=
|
||||
*/
|
||||
* Checks whether this vector is less than the parameter. The metric is
|
||||
* meaningless but it allows Vectors to me used as key in sdt::map, etc.
|
||||
* This function is deprecated. You should specify a seperate comparator to the std:map if you need one.
|
||||
* \param rhs The Vector to compare to.
|
||||
* \return true if this is less than the parameter
|
||||
* \see operator!=
|
||||
* \deprecated
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline bool Vector<Size, StorageType, OperationType>::operator<(const Vector<Size, StorageType, OperationType> &rhs) const
|
||||
{
|
||||
@ -215,10 +217,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Addition operator adds corresponding elements of the two Vectors.
|
||||
\param rhs Vector to add
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Addition operator adds corresponding elements of the two Vectors.
|
||||
* \param rhs The Vector to add
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline Vector<Size, StorageType, OperationType>& Vector<Size, StorageType, OperationType>::operator+=(const Vector<Size, StorageType, OperationType>& rhs)
|
||||
{
|
||||
@ -230,10 +232,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Subtraction operator subtracts corresponding elements of one Vector from the other.
|
||||
\param rhs Vector to subtract
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Subtraction operator subtracts corresponding elements of one Vector from the other.
|
||||
* \param rhs The Vector to subtract
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline Vector<Size, StorageType, OperationType>& Vector<Size, StorageType, OperationType>::operator-=(const Vector<Size, StorageType, OperationType>& rhs)
|
||||
{
|
||||
@ -245,10 +247,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator multiplies corresponding elements of the two Vectors.
|
||||
\param rhs Vector to multiply by
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Multiplication operator multiplies corresponding elements of the two Vectors.
|
||||
* \param rhs The Vector to multiply by
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline Vector<Size, StorageType, OperationType>& Vector<Size, StorageType, OperationType>::operator*=(const Vector<Size, StorageType, OperationType>& rhs)
|
||||
{
|
||||
@ -260,10 +262,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides corresponding elements of one Vector by the other.
|
||||
\param rhs Vector to divide by
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Division operator divides corresponding elements of one Vector by the other.
|
||||
* \param rhs The Vector to divide by
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline Vector<Size, StorageType, OperationType>& Vector<Size, StorageType, OperationType>::operator/=(const Vector<Size, StorageType, OperationType>& rhs)
|
||||
{
|
||||
@ -275,10 +277,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator multiplies each element of the Vector by a number.
|
||||
\param rhs the number the Vector is multiplied by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Multiplication operator multiplies each element of the Vector by a number.
|
||||
* \param rhs The number the Vector is multiplied by.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline Vector<Size, StorageType, OperationType>& Vector<Size, StorageType, OperationType>::operator*=(const StorageType& rhs)
|
||||
{
|
||||
@ -290,10 +292,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides each element of the Vector by a number.
|
||||
\param rhs the number the Vector is divided by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Division operator divides each element of the Vector by a number.
|
||||
* \param rhs The number the Vector is divided by.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline Vector<Size, StorageType, OperationType>& Vector<Size, StorageType, OperationType>::operator/=(const StorageType& rhs)
|
||||
{
|
||||
@ -305,11 +307,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Addition operator adds corresponding elements of the two Vectors.
|
||||
\param lhs Vector to add to.
|
||||
\param rhs Vector to add.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Addition operator adds corresponding elements of the two Vectors.
|
||||
* \param lhs The Vector to add to.
|
||||
* \param rhs The Vector to add.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator+(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs)
|
||||
{
|
||||
@ -319,11 +321,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Subtraction operator subtracts corresponding elements of one Vector from the other.
|
||||
\param lhs Vector to subtract from.
|
||||
\param rhs Vector to subtract.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Subtraction operator subtracts corresponding elements of one Vector from the other.
|
||||
* \param lhs The Vector to subtract from.
|
||||
* \param rhs The Vector to subtract.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator-(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs)
|
||||
{
|
||||
@ -333,11 +335,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator mulitplies corresponding elements of the two Vectors.
|
||||
\param lhs Vector to multiply.
|
||||
\param rhs Vector to multiply by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Multiplication operator mulitplies corresponding elements of the two Vectors.
|
||||
* \param lhs The Vector to multiply.
|
||||
* \param rhs The Vector to multiply by.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs)
|
||||
{
|
||||
@ -347,11 +349,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides corresponding elements of one Vector by the other.
|
||||
\param lhs Vector to divide.
|
||||
\param rhs Vector to divide by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Division operator divides corresponding elements of one Vector by the other.
|
||||
* \param lhs The Vector to divide.
|
||||
* \param rhs The Vector to divide by.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs)
|
||||
{
|
||||
@ -361,11 +363,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator multiplies each element of the Vector by a number.
|
||||
\param lhs the Vector to multiply.
|
||||
\param rhs the number the Vector is multiplied by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Multiplication operator multiplies each element of the Vector by a number.
|
||||
* \param lhs The Vector to multiply.
|
||||
* \param rhs The number the Vector is multiplied by.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs)
|
||||
{
|
||||
@ -375,11 +377,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides each element of the Vector by a number.
|
||||
\param lhs the Vector to divide.
|
||||
\param rhs the number the Vector is divided by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
* Division operator divides each element of the Vector by a number.
|
||||
* \param lhs The Vector to divide.
|
||||
* \param rhs The number the Vector is divided by.
|
||||
* \return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs)
|
||||
{
|
||||
@ -389,11 +391,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Enables the Vector to be used intuitively with output streams such as cout.
|
||||
\param os The output stream to write to.
|
||||
\param vector The Vector to write to the stream.
|
||||
\return A reference to the output stream to allow chaining.
|
||||
*/
|
||||
* Enables the Vector to be used intuitively with output streams such as cout.
|
||||
* \param os The output stream to write to.
|
||||
* \param vector The Vector to write to the stream.
|
||||
* \return A reference to the output stream to allow chaining.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
std::ostream& operator<<(std::ostream& os, const Vector<Size, StorageType, OperationType>& vector)
|
||||
{
|
||||
@ -411,10 +413,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the element at the given position.
|
||||
\param index The index of the element to return.
|
||||
\return The element.
|
||||
*/
|
||||
* Returns the element at the given position.
|
||||
* \param index The index of the element to return.
|
||||
* \return The element.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline StorageType Vector<Size, StorageType, OperationType>::getElement(uint32_t index) const
|
||||
{
|
||||
@ -423,8 +425,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the X component of a 1, 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
* \return A const reference to the X component of a 1, 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline StorageType Vector<Size, StorageType, OperationType>::getX(void) const
|
||||
{
|
||||
@ -432,8 +434,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the Y component of a 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
* \return A const reference to the Y component of a 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline StorageType Vector<Size, StorageType, OperationType>::getY(void) const
|
||||
{
|
||||
@ -441,8 +443,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the Z component of a 3 or 4 dimensional Vector.
|
||||
*/
|
||||
* \return A const reference to the Z component of a 3 or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline StorageType Vector<Size, StorageType, OperationType>::getZ(void) const
|
||||
{
|
||||
@ -454,8 +456,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the W component of a 4 dimensional Vector.
|
||||
*/
|
||||
* \return A const reference to the W component of a 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline StorageType Vector<Size, StorageType, OperationType>::getW(void) const
|
||||
{
|
||||
@ -467,9 +469,9 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\param index The index of the element to set.
|
||||
\param tValue The new value for the element.
|
||||
*/
|
||||
* \param index The index of the element to set.
|
||||
* \param tValue The new value for the element.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline void Vector<Size, StorageType, OperationType>::setElement(uint32_t index, StorageType tValue)
|
||||
{
|
||||
@ -478,10 +480,10 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Sets several elements of a vector at once.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
*/
|
||||
* Sets several elements of a vector at once.
|
||||
* \param x The X component to set.
|
||||
* \param y The Y component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y)
|
||||
{
|
||||
@ -491,11 +493,11 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Sets several elements of a vector at once.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
*/
|
||||
* Sets several elements of a vector at once.
|
||||
* \param x The X component to set.
|
||||
* \param y The Y component to set.
|
||||
* \param z The Z component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z)
|
||||
{
|
||||
@ -508,12 +510,12 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Sets several elements of a vector at once.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
\param w w component to set.
|
||||
*/
|
||||
* Sets several elements of a vector at once.
|
||||
* \param x The X component to set.
|
||||
* \param y The Y component to set.
|
||||
* \param z The Z component to set.
|
||||
* \param w The W component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename StorageType, typename OperationType>
|
||||
inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z, StorageType w)
|
||||
{
|
||||
@ -527,8 +529,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\param tX The new value for the X component of a 1, 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
* \param tX The new value for the X component of a 1, 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline void Vector<Size, StorageType, OperationType>::setX(StorageType tX)
|
||||
{
|
||||
@ -536,8 +538,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\param tY The new value for the Y component of a 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
* \param tY The new value for the Y component of a 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline void Vector<Size, StorageType, OperationType>::setY(StorageType tY)
|
||||
{
|
||||
@ -545,8 +547,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\param tZ The new value for the Z component of a 3 or 4 dimensional Vector.
|
||||
*/
|
||||
* \param tZ The new value for the Z component of a 3 or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline void Vector<Size, StorageType, OperationType>::setZ(StorageType tZ)
|
||||
{
|
||||
@ -557,8 +559,8 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\param tW The new value for the W component of a 4 dimensional Vector.
|
||||
*/
|
||||
* \param tW The new value for the W component of a 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline void Vector<Size, StorageType, OperationType>::setW(StorageType tW)
|
||||
{
|
||||
@ -569,56 +571,56 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
\note This function does not make much sense on integer Vectors.
|
||||
\return Length of the Vector.
|
||||
*/
|
||||
* \note This function always returns a single precision floating point value, even when the StorageType is a double precision floating point value or an integer.
|
||||
* \return The length of the Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline double Vector<Size, StorageType, OperationType>::length(void) const
|
||||
inline float Vector<Size, StorageType, OperationType>::length(void) const
|
||||
{
|
||||
return sqrt(lengthSquared());
|
||||
return sqrt(static_cast<float>(lengthSquared()));
|
||||
}
|
||||
|
||||
/**
|
||||
\return Squared length of the Vector.
|
||||
*/
|
||||
* \return The squared length of the Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline double Vector<Size, StorageType, OperationType>::lengthSquared(void) const
|
||||
inline OperationType Vector<Size, StorageType, OperationType>::lengthSquared(void) const
|
||||
{
|
||||
double result = 0.0f;
|
||||
OperationType tLengthSquared = static_cast<OperationType>(0);
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
result += m_tElements[ct] * m_tElements[ct];
|
||||
tLengthSquared += static_cast<OperationType>(m_tElements[ct]) * static_cast<OperationType>(m_tElements[ct]);
|
||||
}
|
||||
return result;
|
||||
return tLengthSquared;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is commutative, such that a.angleTo(b) == b.angleTo(a). The angle
|
||||
returned is in radians and varies between 0 and 3.14(pi). It is always positive.
|
||||
|
||||
\note This function does not make much sense on integer Vectors.
|
||||
|
||||
\param vector The Vector to find the angle to.
|
||||
\return The angle between them in radians.
|
||||
*/
|
||||
* This function is commutative, such that a.angleTo(b) == b.angleTo(a). The angle
|
||||
* returned is in radians and varies between 0 and 3.14(pi). It is always positive.
|
||||
*
|
||||
* \note This function always returns a single precision floating point value, even when the StorageType is a double precision floating point value or an integer.
|
||||
*
|
||||
* \param vector The Vector to find the angle to.
|
||||
* \return The angle between them in radians.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline double Vector<Size, StorageType, OperationType>::angleTo(const Vector<Size, StorageType, OperationType>& vector) const
|
||||
inline float Vector<Size, StorageType, OperationType>::angleTo(const Vector<Size, StorageType, OperationType>& vector) const
|
||||
{
|
||||
return acos(dot(vector) / (vector.length() * this->length()));
|
||||
return acos(static_cast<float>(dot(vector)) / (vector.length() * this->length()));
|
||||
}
|
||||
|
||||
/**
|
||||
This function is used to calculate the cross product of two Vectors.
|
||||
The cross product is the Vector which is perpendicular to the two
|
||||
given Vectors. It is worth remembering that, unlike the dot product,
|
||||
it is not commutative. E.g a.b != b.a. The cross product obeys the
|
||||
right-hand rule such that if the two vectors are given by the index
|
||||
finger and middle finger respectively then the cross product is given
|
||||
by the thumb.
|
||||
\param vector The vector to cross with this
|
||||
\return The value of the cross product.
|
||||
\see dot()
|
||||
*/
|
||||
* This function is used to calculate the cross product of two Vectors.
|
||||
* The cross product is the Vector which is perpendicular to the two
|
||||
* given Vectors. It is worth remembering that, unlike the dot product,
|
||||
* it is not commutative. E.g a.b != b.a. The cross product obeys the
|
||||
* right-hand rule such that if the two vectors are given by the index
|
||||
* finger and middle finger respectively then the cross product is given
|
||||
* by the thumb.
|
||||
* \param vector The vector to cross with this
|
||||
* \return The value of the cross product.
|
||||
* \see dot()
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline Vector<Size, StorageType, OperationType> Vector<Size, StorageType, OperationType>::cross(const Vector<Size, StorageType, OperationType>& vector) const
|
||||
{
|
||||
@ -629,40 +631,39 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
/**
|
||||
Calculates the dot product of the Vector and the parameter.
|
||||
This function is commutative, such that a.dot(b) == b.dot(a).
|
||||
\param rhs The Vector to find the dot product with.
|
||||
\return The value of the dot product.
|
||||
\see cross()
|
||||
*/
|
||||
* Calculates the dot product of the Vector and the parameter.
|
||||
* This function is commutative, such that a.dot(b) == b.dot(a).
|
||||
* \param rhs The Vector to find the dot product with.
|
||||
* \return The value of the dot product.
|
||||
* \see cross()
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline StorageType Vector<Size, StorageType, OperationType>::dot(const Vector<Size, StorageType, OperationType>& rhs) const
|
||||
inline OperationType Vector<Size, StorageType, OperationType>::dot(const Vector<Size, StorageType, OperationType>& rhs) const
|
||||
{
|
||||
StorageType dotProduct = static_cast<StorageType>(0);
|
||||
OperationType dotProduct = static_cast<OperationType>(0);
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
dotProduct += m_tElements[ct] * rhs.m_tElements[ct];
|
||||
dotProduct += static_cast<OperationType>(m_tElements[ct]) * static_cast<OperationType>(rhs.m_tElements[ct]);
|
||||
}
|
||||
return dotProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
Divides the i, j, and k components by the length to give a Vector of length 1.0.
|
||||
|
||||
\note This function does not make much sense on integer Vectors.
|
||||
*/
|
||||
* Divides the i, j, and k components by the length to give a Vector of length 1.0. If the vector is
|
||||
* very short (or zero) then a divide by zero may cause elements to take on invalid values. You may
|
||||
* want to check for this before normalising.
|
||||
*
|
||||
* \note You should not attempt to normalise a vector whose StorageType is an integer.
|
||||
*/
|
||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||
inline void Vector<Size, StorageType, OperationType>::normalise(void)
|
||||
{
|
||||
StorageType tLength = static_cast<StorageType>(this->length());
|
||||
//FIXME - throw div by zero exception?
|
||||
if(tLength < 0.0001f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
float fLength = this->length();
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] /= tLength;
|
||||
// Standard float rules apply for divide-by-zero
|
||||
m_tElements[ct] /= fLength;
|
||||
assert(m_tElements[ct] == m_tElements[ct]); //Will assert if NAN
|
||||
}
|
||||
}
|
||||
}//namespace PolyVox
|
||||
|
@ -1,181 +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.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "PolyVoxCore/MeshDecimator.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<>
|
||||
POLYVOX_API void MeshDecimator<PositionMaterial>::fillInitialVertexMetadata(std::vector<InitialVertexMetadata>& vecVertexMetadata)
|
||||
{
|
||||
vecVertexMetadata.clear();
|
||||
vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
//Initialise the metadata
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
vecVertexMetadata[ct].normal.setElements(0,0,0);
|
||||
vecVertexMetadata[ct].isOnMaterialEdge = false;
|
||||
vecVertexMetadata[ct].isOnRegionFace.reset();
|
||||
}
|
||||
|
||||
//Identify duplicate vertices, as they lie on the material edge. To do this we convert into integers and sort
|
||||
//(first on z, then y, then x). They should be mostly in order as this is the order they come out of the
|
||||
//CubicSurfaceExtractor in. Duplicates are now neighbours in the resulting list so just scan through for pairs.
|
||||
std::vector<IntVertex> intVertices;
|
||||
intVertices.reserve(m_pOutputMesh->m_vecVertices.size());
|
||||
for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++)
|
||||
{
|
||||
const Vector3DFloat& floatPos = m_pOutputMesh->m_vecVertices[ct].position;
|
||||
IntVertex intVertex(static_cast<uint32_t>(floatPos.getX()), static_cast<uint32_t>(floatPos.getY()), static_cast<uint32_t>(floatPos.getZ()), ct);
|
||||
intVertices.push_back(intVertex);
|
||||
}
|
||||
|
||||
//Do the sorting so that duplicate become neighbours
|
||||
sort(intVertices.begin(), intVertices.end());
|
||||
|
||||
//Find neighbours which are duplicates.
|
||||
for(uint32_t ct = 0; ct < intVertices.size() - 1; ct++)
|
||||
{
|
||||
const IntVertex& v0 = intVertices[ct+0];
|
||||
const IntVertex& v1 = intVertices[ct+1];
|
||||
|
||||
if((v0.x == v1.x) && (v0.y == v1.y) && (v0.z == v1.z))
|
||||
{
|
||||
vecVertexMetadata[v0.index].isOnMaterialEdge = true;
|
||||
vecVertexMetadata[v1.index].isOnMaterialEdge = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Compute an approcimation to the normal, used when deciding if an edge can collapse.
|
||||
for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++)
|
||||
{
|
||||
Vector3DFloat sumOfNormals(0.0f,0.0f,0.0f);
|
||||
for(vector<uint32_t>::iterator iter = trianglesUsingVertex[ct].begin(); iter != trianglesUsingVertex[ct].end(); iter++)
|
||||
{
|
||||
sumOfNormals += m_vecTriangles[*iter].normal;
|
||||
}
|
||||
|
||||
vecVertexMetadata[ct].normal = sumOfNormals;
|
||||
vecVertexMetadata[ct].normal.normalise();
|
||||
}
|
||||
|
||||
//Identify those vertices on the edge of a region. Care will need to be taken when moving them.
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
Region regTransformed = m_pOutputMesh->m_Region;
|
||||
regTransformed.shift(regTransformed.getLowerCorner() * static_cast<int32_t>(-1));
|
||||
|
||||
//Plus and minus X
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f);
|
||||
//Plus and minus Y
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f);
|
||||
//Plus and minus Z
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
POLYVOX_API void MeshDecimator<PositionMaterialNormal>::fillInitialVertexMetadata(std::vector<InitialVertexMetadata>& vecVertexMetadata)
|
||||
{
|
||||
vecVertexMetadata.clear();
|
||||
vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
|
||||
//Initialise the metadata
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
vecVertexMetadata[ct].isOnRegionFace.reset();
|
||||
vecVertexMetadata[ct].isOnMaterialEdge = false;
|
||||
vecVertexMetadata[ct].normal = m_pOutputMesh->m_vecVertices[ct].normal;
|
||||
}
|
||||
|
||||
//Identify those vertices on the edge of a region. Care will need to be taken when moving them.
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
Region regTransformed = m_pOutputMesh->m_Region;
|
||||
regTransformed.shift(regTransformed.getLowerCorner() * static_cast<int32_t>(-1));
|
||||
|
||||
//Plus and minus X
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f);
|
||||
//Plus and minus Y
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f);
|
||||
//Plus and minus Z
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f);
|
||||
}
|
||||
|
||||
//If all three vertices have the same material then we are not on a material edge. If any vertex has a different
|
||||
//material then all three vertices are on a material edge. E.g. If one vertex has material 'a' and the other two
|
||||
//have material 'b', then the two 'b's are still on an edge (with 'a') even though they are the same as eachother.
|
||||
for(uint32_t ct = 0; ct < m_vecTriangles.size(); ct++)
|
||||
{
|
||||
uint32_t v0 = m_vecTriangles[ct].v0;
|
||||
uint32_t v1 = m_vecTriangles[ct].v1;
|
||||
uint32_t v2 = m_vecTriangles[ct].v2;
|
||||
|
||||
bool allMatch =
|
||||
(m_pOutputMesh->m_vecVertices[v0].material - m_pOutputMesh->m_vecVertices[v1].material < 0.001f) &&
|
||||
(m_pOutputMesh->m_vecVertices[v1].material - m_pOutputMesh->m_vecVertices[v2].material < 0.001f);
|
||||
|
||||
if(!allMatch)
|
||||
{
|
||||
vecVertexMetadata[v0].isOnMaterialEdge = true;
|
||||
vecVertexMetadata[v1].isOnMaterialEdge = true;
|
||||
vecVertexMetadata[v2].isOnMaterialEdge = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
POLYVOX_API bool MeshDecimator<PositionMaterialNormal>::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[uDst].normal) < m_fMinDotProductForCollapse)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//With the marching cubes surface we honour the user specified threshold
|
||||
return !collapseChangesFaceNormals(uSrc, uDst, m_fMinDotProductForCollapse);
|
||||
}
|
||||
|
||||
template<>
|
||||
POLYVOX_API bool MeshDecimator<PositionMaterial>::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
//We don't actually use the normal here, because we want to allow face
|
||||
//vertices to collapse onto edge vertices. Simply checking whether anything
|
||||
//has flipped has proved to be the most robust approach, though rather slow.
|
||||
//It's not sufficient to just check the normals, there can be holes in the middle
|
||||
//of the mesh for example.
|
||||
|
||||
//User specified threshold is not used for cubic surface, any
|
||||
//movement is too much (but allow for floating point error).
|
||||
return !collapseChangesFaceNormals(uSrc, uDst, 0.999f);
|
||||
}
|
||||
}
|
@ -23,236 +23,449 @@ freely, subject to the following restrictions:
|
||||
|
||||
#include "PolyVoxCore/Region.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
*/
|
||||
const Region Region::MaxRegion
|
||||
(
|
||||
Vector3DInt32((std::numeric_limits<int32_t>::min)(), (std::numeric_limits<int32_t>::min)(), (std::numeric_limits<int32_t>::min)()),
|
||||
Vector3DInt32((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)())
|
||||
);
|
||||
|
||||
/**
|
||||
* This Region is not considered valid as defined by isValid(). It's main application
|
||||
* is to initialise a Region to this value and then() accumulate positions. The result
|
||||
* of this will be a Region which encompasses all positions specified.
|
||||
*/
|
||||
const Region Region::InvertedRegion
|
||||
(
|
||||
Vector3DInt32((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)()),
|
||||
Vector3DInt32((std::numeric_limits<int32_t>::min)(), (std::numeric_limits<int32_t>::min)(), (std::numeric_limits<int32_t>::min)())
|
||||
);
|
||||
|
||||
Region::Region()
|
||||
:m_v3dLowerCorner(0,0,0)
|
||||
,m_v3dUpperCorner(0,0,0)
|
||||
/**
|
||||
* \param iX The 'x' component of the position to accumulate.
|
||||
* \param iY The 'y' component of the position to accumulate.
|
||||
* \param iZ The 'z' component of the position to accumulate.
|
||||
*/
|
||||
void Region::accumulate(int32_t iX, int32_t iY, int32_t iZ)
|
||||
{
|
||||
}
|
||||
|
||||
Region::Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner)
|
||||
:m_v3dLowerCorner(v3dLowerCorner)
|
||||
,m_v3dUpperCorner(v3dUpperCorner)
|
||||
{
|
||||
//Check the region is valid.
|
||||
assert(m_v3dUpperCorner.getX() >= m_v3dLowerCorner.getX());
|
||||
assert(m_v3dUpperCorner.getY() >= m_v3dLowerCorner.getY());
|
||||
assert(m_v3dUpperCorner.getZ() >= m_v3dLowerCorner.getZ());
|
||||
}
|
||||
|
||||
Region::Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ)
|
||||
:m_v3dLowerCorner(iLowerX, iLowerY, iLowerZ)
|
||||
,m_v3dUpperCorner(iUpperX, iUpperY, iUpperZ)
|
||||
{
|
||||
//Check the region is valid.
|
||||
assert(m_v3dUpperCorner.getX() >= m_v3dLowerCorner.getX());
|
||||
assert(m_v3dUpperCorner.getY() >= m_v3dLowerCorner.getY());
|
||||
assert(m_v3dUpperCorner.getZ() >= m_v3dLowerCorner.getZ());
|
||||
m_iLowerX = ((std::min)(m_iLowerX, iX));
|
||||
m_iLowerY = ((std::min)(m_iLowerY, iY));
|
||||
m_iLowerZ = ((std::min)(m_iLowerZ, iZ));
|
||||
m_iUpperX = ((std::max)(m_iUpperX, iX));
|
||||
m_iUpperY = ((std::max)(m_iUpperY, iY));
|
||||
m_iUpperZ = ((std::max)(m_iUpperZ, iZ));
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Regions are equal.
|
||||
\param rhs The Region to compare to.
|
||||
\return true if the Regions match.
|
||||
\see operator!=
|
||||
*/
|
||||
* \param v3dPos The position to accumulate.
|
||||
*/
|
||||
void Region::accumulate(const Vector3DInt32& v3dPos)
|
||||
{
|
||||
accumulate(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this is not the same as computing the union of two Regions (as the result of
|
||||
* such a union may not be a shape which can be exactly represented by a Region). Instead,
|
||||
* the result is simply big enough to contain both this Region and the one passed as a parameter.
|
||||
* \param reg The Region to accumulate. This must be valid as defined by the isValid() function.
|
||||
* \sa isValid()
|
||||
*/
|
||||
void Region::accumulate(const Region& reg)
|
||||
{
|
||||
assert(reg.isValid()); //The result of accumulating an invalid region is not defined.
|
||||
|
||||
m_iLowerX = ((std::min)(m_iLowerX, reg.getLowerX()));
|
||||
m_iLowerY = ((std::min)(m_iLowerY, reg.getLowerY()));
|
||||
m_iLowerZ = ((std::min)(m_iLowerZ, reg.getLowerZ()));
|
||||
m_iUpperX = ((std::max)(m_iUpperX, reg.getUpperX()));
|
||||
m_iUpperY = ((std::max)(m_iUpperY, reg.getUpperY()));
|
||||
m_iUpperZ = ((std::max)(m_iUpperZ, reg.getUpperZ()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Region and clears all extents to zero.
|
||||
*/
|
||||
Region::Region()
|
||||
:m_iLowerX(0)
|
||||
,m_iLowerY(0)
|
||||
,m_iLowerZ(0)
|
||||
,m_iUpperX(0)
|
||||
,m_iUpperY(0)
|
||||
,m_iUpperZ(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Region and sets the lower and upper corners to the specified values.
|
||||
* \param v3dLowerCorner The desired lower corner of the Region.
|
||||
* \param v3dUpperCorner The desired upper corner of the Region.
|
||||
*/
|
||||
Region::Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner)
|
||||
:m_iLowerX(v3dLowerCorner.getX())
|
||||
,m_iLowerY(v3dLowerCorner.getY())
|
||||
,m_iLowerZ(v3dLowerCorner.getZ())
|
||||
,m_iUpperX(v3dUpperCorner.getX())
|
||||
,m_iUpperY(v3dUpperCorner.getY())
|
||||
,m_iUpperZ(v3dUpperCorner.getZ())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Region and sets the extents to the specified values.
|
||||
* \param iLowerX The desired lower 'x' extent of the Region.
|
||||
* \param iLowerY The desired lower 'y' extent of the Region.
|
||||
* \param iLowerZ The desired lower 'z' extent of the Region.
|
||||
* \param iUpperX The desired upper 'x' extent of the Region.
|
||||
* \param iUpperY The desired upper 'y' extent of the Region.
|
||||
* \param iUpperZ The desired upper 'z' extent of the Region.
|
||||
*/
|
||||
Region::Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ)
|
||||
:m_iLowerX(iLowerX)
|
||||
,m_iLowerY(iLowerY)
|
||||
,m_iLowerZ(iLowerZ)
|
||||
,m_iUpperX(iUpperX)
|
||||
,m_iUpperY(iUpperY)
|
||||
,m_iUpperZ(iUpperZ)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Two regions are considered equal if all their extents match.
|
||||
* \param rhs The Region to compare to.
|
||||
* \return true if the Regions match.
|
||||
* \sa operator!=
|
||||
*/
|
||||
bool Region::operator==(const Region& rhs) const
|
||||
{
|
||||
return ((m_v3dLowerCorner == rhs.m_v3dLowerCorner) && (m_v3dUpperCorner == rhs.m_v3dUpperCorner));
|
||||
return ((m_iLowerX == rhs.m_iLowerX) && (m_iLowerY == rhs.m_iLowerY) && (m_iLowerZ == rhs.m_iLowerZ)
|
||||
&& (m_iUpperX == rhs.m_iUpperX) && (m_iUpperY == rhs.m_iUpperY) && (m_iUpperZ == rhs.m_iUpperZ));
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Regions are not equal.
|
||||
\param rhs The Region to compare to.
|
||||
\return true if the Regions do not match.
|
||||
\see operator==
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Two regions are considered different if any of their extents differ.
|
||||
/// \param rhs The Region to compare to.
|
||||
/// \return true if the Regions are different.
|
||||
/// \sa operator==
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Region::operator!=(const Region& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
const Vector3DInt32& Region::getLowerCorner(void) const
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in all directions. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param fX The 'x' position of the point to test.
|
||||
* \param fY The 'y' position of the point to test.
|
||||
* \param fZ The 'z' position of the point to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPoint(float fX, float fY, float fZ, float boundary) const
|
||||
{
|
||||
return m_v3dLowerCorner;
|
||||
}
|
||||
|
||||
const Vector3DInt32& Region::getUpperCorner(void) const
|
||||
{
|
||||
return m_v3dUpperCorner;
|
||||
}
|
||||
|
||||
int32_t Region::getWidthInVoxels(void) const
|
||||
{
|
||||
return getWidthInCells() + 1;
|
||||
}
|
||||
|
||||
int32_t Region::getHeightInVoxels(void) const
|
||||
{
|
||||
return getHeightInCells() + 1;
|
||||
}
|
||||
|
||||
int32_t Region::getDepthInVoxels(void) const
|
||||
{
|
||||
return getDepthInCells() + 1;
|
||||
}
|
||||
|
||||
Vector3DInt32 Region::getDimensionsInVoxels(void) const
|
||||
{
|
||||
return getDimensionsInCells() + Vector3DInt32(1, 1, 1);
|
||||
}
|
||||
|
||||
int32_t Region::getWidthInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner.getX() - m_v3dLowerCorner.getX();
|
||||
}
|
||||
|
||||
int32_t Region::getHeightInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner.getY() - m_v3dLowerCorner.getY();
|
||||
}
|
||||
|
||||
Vector3DInt32 Region::getDimensionsInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner - m_v3dLowerCorner;
|
||||
}
|
||||
|
||||
int32_t Region::getDepthInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner.getZ() - m_v3dLowerCorner.getZ();
|
||||
}
|
||||
|
||||
void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner)
|
||||
{
|
||||
m_v3dLowerCorner = v3dLowerCorner;
|
||||
}
|
||||
|
||||
void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner)
|
||||
{
|
||||
m_v3dUpperCorner = v3dUpperCorner;
|
||||
return (fX <= m_iUpperX - boundary)
|
||||
&& (fY <= m_iUpperY - boundary)
|
||||
&& (fZ <= m_iUpperZ - boundary)
|
||||
&& (fX >= m_iLowerX + boundary)
|
||||
&& (fY >= m_iLowerY + boundary)
|
||||
&& (fZ >= m_iLowerZ + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in all directions. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPoint(const Vector3DFloat& pos, float boundary) const
|
||||
{
|
||||
return (pos.getX() <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos.getY() <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos.getZ() <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos.getX() >= m_v3dLowerCorner.getX() + boundary)
|
||||
&& (pos.getY() >= m_v3dLowerCorner.getY() + boundary)
|
||||
&& (pos.getZ() >= m_v3dLowerCorner.getZ() + boundary);
|
||||
return containsPoint(pos.getX(), pos.getY(), pos.getZ(), boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in all directions. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param iX The 'x' position of the point to test.
|
||||
* \param iY The 'y' position of the point to test.
|
||||
* \param iZ The 'z' position of the point to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPoint(int32_t iX, int32_t iY, int32_t iZ, uint8_t boundary) const
|
||||
{
|
||||
return (iX <= m_iUpperX - boundary)
|
||||
&& (iY <= m_iUpperY - boundary)
|
||||
&& (iZ <= m_iUpperZ - boundary)
|
||||
&& (iX >= m_iLowerX + boundary)
|
||||
&& (iY >= m_iLowerY + boundary)
|
||||
&& (iZ >= m_iLowerZ + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in all directions. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPoint(const Vector3DInt32& pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos.getX() <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos.getY() <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos.getZ() <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos.getX() >= m_v3dLowerCorner.getX() + boundary)
|
||||
&& (pos.getY() >= m_v3dLowerCorner.getY() + boundary)
|
||||
&& (pos.getZ() >= m_v3dLowerCorner.getZ() + boundary);
|
||||
return containsPoint(pos.getX(), pos.getY(), pos.getZ(), boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in the 'x' direction. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPointInX(float pos, float boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getX() + boundary);
|
||||
return (pos <= m_iUpperX - boundary)
|
||||
&& (pos >= m_iLowerX + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in the 'x' direction. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPointInX(int32_t pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getX() + boundary);
|
||||
return (pos <= m_iUpperX - boundary)
|
||||
&& (pos >= m_iLowerX + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in the 'y' direction. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPointInY(float pos, float boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getY() + boundary);
|
||||
return (pos <= m_iUpperY - boundary)
|
||||
&& (pos >= m_iLowerY + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in the 'y' direction. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPointInY(int32_t pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getY() + boundary);
|
||||
return (pos <= m_iUpperY - boundary)
|
||||
&& (pos >= m_iLowerY + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in the 'z' direction. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPointInZ(float pos, float boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getZ() + boundary);
|
||||
return (pos <= m_iUpperZ - boundary)
|
||||
&& (pos >= m_iLowerZ + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* The boundary value can be used to ensure a position is only considered to be inside
|
||||
* the Region if it is that far in in the 'z' direction. Also, the test is inclusive such
|
||||
* that positions lying exactly on the edge of the Region are considered to be inside it.
|
||||
* \param pos The position to test.
|
||||
* \param boundary The desired boundary value.
|
||||
*/
|
||||
bool Region::containsPointInZ(int32_t pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getZ() + boundary);
|
||||
return (pos <= m_iUpperZ - boundary)
|
||||
&& (pos >= m_iLowerZ + boundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* After calling this functions, the extents of this Region are given by the intersection
|
||||
* of this Region and the one it was cropped to.
|
||||
* \param other The Region to crop to.
|
||||
*/
|
||||
void Region::cropTo(const Region& other)
|
||||
{
|
||||
m_v3dLowerCorner.setX((std::max)(m_v3dLowerCorner.getX(), other.m_v3dLowerCorner.getX()));
|
||||
m_v3dLowerCorner.setY((std::max)(m_v3dLowerCorner.getY(), other.m_v3dLowerCorner.getY()));
|
||||
m_v3dLowerCorner.setZ((std::max)(m_v3dLowerCorner.getZ(), other.m_v3dLowerCorner.getZ()));
|
||||
m_v3dUpperCorner.setX((std::min)(m_v3dUpperCorner.getX(), other.m_v3dUpperCorner.getX()));
|
||||
m_v3dUpperCorner.setY((std::min)(m_v3dUpperCorner.getY(), other.m_v3dUpperCorner.getY()));
|
||||
m_v3dUpperCorner.setZ((std::min)(m_v3dUpperCorner.getZ(), other.m_v3dUpperCorner.getZ()));
|
||||
m_iLowerX = ((std::max)(m_iLowerX, other.m_iLowerX));
|
||||
m_iLowerY = ((std::max)(m_iLowerY, other.m_iLowerY));
|
||||
m_iLowerZ = ((std::max)(m_iLowerZ, other.m_iLowerZ));
|
||||
m_iUpperX = ((std::min)(m_iUpperX, other.m_iUpperX));
|
||||
m_iUpperY = ((std::min)(m_iUpperY, other.m_iUpperY));
|
||||
m_iUpperZ = ((std::min)(m_iUpperZ, other.m_iUpperZ));
|
||||
}
|
||||
|
||||
/// \deprecated Use getDepthInVoxels() or getDepthInCells() instead
|
||||
int32_t Region::depth(void) const
|
||||
/**
|
||||
* The same amount of growth is applied in all directions. Negative growth
|
||||
* is possible but you should prefer the shrink() function for clarity.
|
||||
* \param iAmount The amount to grow by.
|
||||
*/
|
||||
void Region::grow(int32_t iAmount)
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner.getZ() - m_v3dLowerCorner.getZ();
|
||||
m_iLowerX -= iAmount;
|
||||
m_iLowerY -= iAmount;
|
||||
m_iLowerZ -= iAmount;
|
||||
|
||||
m_iUpperX += iAmount;
|
||||
m_iUpperY += iAmount;
|
||||
m_iUpperZ += iAmount;
|
||||
}
|
||||
|
||||
/// \deprecated Use getHeightInVoxels() or getHeightInCells() instead
|
||||
int32_t Region::height(void) const
|
||||
/**
|
||||
* The amount can be specified seperatly for each direction. Negative growth
|
||||
* is possible but you should prefer the shrink() function for clarity.
|
||||
* \param iAmountX The amount to grow by in 'x'.
|
||||
* \param iAmountY The amount to grow by in 'y'.
|
||||
* \param iAmountZ The amount to grow by in 'z'.
|
||||
*/
|
||||
void Region::grow(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ)
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner.getY() - m_v3dLowerCorner.getY();
|
||||
m_iLowerX -= iAmountX;
|
||||
m_iLowerY -= iAmountY;
|
||||
m_iLowerZ -= iAmountZ;
|
||||
|
||||
m_iUpperX += iAmountX;
|
||||
m_iUpperY += iAmountY;
|
||||
m_iUpperZ += iAmountZ;
|
||||
}
|
||||
|
||||
void Region::shift(const Vector3DInt32& amount)
|
||||
/**
|
||||
* The amount can be specified seperatly for each direction. Negative growth
|
||||
* is possible but you should prefer the shrink() function for clarity.
|
||||
* \param v3dAmount The amount to grow by (one component for each direction).
|
||||
*/
|
||||
void Region::grow(const Vector3DInt32& v3dAmount)
|
||||
{
|
||||
m_v3dLowerCorner += amount;
|
||||
m_v3dUpperCorner += amount;
|
||||
grow(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ());
|
||||
}
|
||||
|
||||
void Region::shiftLowerCorner(const Vector3DInt32& amount)
|
||||
/**
|
||||
*/
|
||||
bool Region::isValid(void) const
|
||||
{
|
||||
m_v3dLowerCorner += amount;
|
||||
return (m_iUpperX >= m_iLowerX) && (m_iUpperY >= m_iLowerY) && (m_iUpperZ >= m_iLowerZ);
|
||||
}
|
||||
|
||||
void Region::shiftUpperCorner(const Vector3DInt32& amount)
|
||||
/**
|
||||
* \param iAmountX The amount to move the Region by in 'x'.
|
||||
* \param iAmountY The amount to move the Region by in 'y'.
|
||||
* \param iAmountZ The amount to move the Region by in 'z'.
|
||||
*/
|
||||
void Region::shift(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ)
|
||||
{
|
||||
m_v3dUpperCorner += amount;
|
||||
shiftLowerCorner(iAmountX, iAmountY, iAmountZ);
|
||||
shiftUpperCorner(iAmountX, iAmountY, iAmountZ);
|
||||
}
|
||||
|
||||
/// \deprecated Use getDimensionsInVoxels() or getDimensionsInCells() instead
|
||||
Vector3DInt32 Region::dimensions(void)
|
||||
/**
|
||||
* \param v3dAmount The amount to move the Region by.
|
||||
*/
|
||||
void Region::shift(const Vector3DInt32& v3dAmount)
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner - m_v3dLowerCorner;
|
||||
shiftLowerCorner(v3dAmount);
|
||||
shiftUpperCorner(v3dAmount);
|
||||
}
|
||||
|
||||
/// \deprecated Use getWidthInVoxels() or getWidthInCells() instead
|
||||
int32_t Region::width(void) const
|
||||
/**
|
||||
* \param iAmountX The amount to move the lower corner by in 'x'.
|
||||
* \param iAmountY The amount to move the lower corner by in 'y'.
|
||||
* \param iAmountZ The amount to move the lower corner by in 'z'.
|
||||
*/
|
||||
void Region::shiftLowerCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ)
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner.getX() - m_v3dLowerCorner.getX();
|
||||
m_iLowerX += iAmountX;
|
||||
m_iLowerY += iAmountY;
|
||||
m_iLowerZ += iAmountZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param v3dAmount The amount to move the lower corner by.
|
||||
*/
|
||||
void Region::shiftLowerCorner(const Vector3DInt32& v3dAmount)
|
||||
{
|
||||
shiftLowerCorner(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* \param iAmountX The amount to move the upper corner by in 'x'.
|
||||
* \param iAmountY The amount to move the upper corner by in 'y'.
|
||||
* \param iAmountZ The amount to move the upper corner by in 'z'.
|
||||
*/
|
||||
void Region::shiftUpperCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ)
|
||||
{
|
||||
m_iUpperX += iAmountX;
|
||||
m_iUpperY += iAmountY;
|
||||
m_iUpperZ += iAmountZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param v3dAmount The amount to move the upper corner by.
|
||||
*/
|
||||
void Region::shiftUpperCorner(const Vector3DInt32& v3dAmount)
|
||||
{
|
||||
shiftUpperCorner(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* The same amount of shrinkage is applied in all directions. Negative shrinkage
|
||||
* is possible but you should prefer the grow() function for clarity.
|
||||
* \param iAmount The amount to shrink by.
|
||||
*/
|
||||
void Region::shrink(int32_t iAmount)
|
||||
{
|
||||
m_iLowerX += iAmount;
|
||||
m_iLowerY += iAmount;
|
||||
m_iLowerZ += iAmount;
|
||||
|
||||
m_iUpperX -= iAmount;
|
||||
m_iUpperY -= iAmount;
|
||||
m_iUpperZ -= iAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount can be specified seperatly for each direction. Negative shrinkage
|
||||
* is possible but you should prefer the grow() function for clarity.
|
||||
* \param iAmountX The amount to shrink by in 'x'.
|
||||
* \param iAmountY The amount to shrink by in 'y'.
|
||||
* \param iAmountZ The amount to shrink by in 'z'.
|
||||
*/
|
||||
void Region::shrink(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ)
|
||||
{
|
||||
m_iLowerX += iAmountX;
|
||||
m_iLowerY += iAmountY;
|
||||
m_iLowerZ += iAmountZ;
|
||||
|
||||
m_iUpperX -= iAmountX;
|
||||
m_iUpperY -= iAmountY;
|
||||
m_iUpperZ -= iAmountZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount can be specified seperatly for each direction. Negative shrinkage
|
||||
* is possible but you should prefer the grow() function for clarity.
|
||||
* \param v3dAmount The amount to shrink by (one component for each direction).
|
||||
*/
|
||||
void Region::shrink(const Vector3DInt32& v3dAmount)
|
||||
{
|
||||
shrink(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ());
|
||||
}
|
||||
}
|
||||
|
@ -1,43 +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.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "PolyVoxCore/SimpleInterface.h"
|
||||
|
||||
//DOESN'T BELONG HERE - JUST FOR TESTING!!
|
||||
#include "PolyVoxCore/Density.h"
|
||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
void extractCubicMesh(Volume& volume, const Region& region, Mesh& resultMesh)
|
||||
{
|
||||
CubicSurfaceExtractorWithNormals< SimpleVolume<MaterialDensityPair88> > surfaceExtractor(&volume, region, &resultMesh);
|
||||
surfaceExtractor.execute();
|
||||
}
|
||||
|
||||
void extractSmoothMesh(Volume& volume, const Region& region, Mesh& resultMesh)
|
||||
{
|
||||
MarchingCubesSurfaceExtractor< SimpleVolume<MaterialDensityPair88> > surfaceExtractor(&volume, region, &resultMesh);
|
||||
surfaceExtractor.execute();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user