Merge branch 'develop' into feature/cubiquity-version
Conflicts: library/PolyVoxCore/include/PolyVoxCore/Region.h library/PolyVoxCore/source/Region.cpp
This commit is contained in:
		| @@ -73,10 +73,7 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex) | ||||
| 	{ | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
| 		POLYVOX_THROW_IF(uIndex >= m_pDimensions[0], std::out_of_range, "Array index out of range"); | ||||
|  | ||||
| 		return | ||||
| 			SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]], | ||||
| @@ -95,10 +92,7 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	const SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex) const | ||||
| 	{ | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
| 		POLYVOX_THROW_IF(uIndex >= m_pDimensions[0], std::out_of_range, "Array index out of range"); | ||||
|  | ||||
| 		return | ||||
| 			SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]], | ||||
| @@ -147,10 +141,7 @@ namespace PolyVox | ||||
| 		m_uNoOfElements = 1; | ||||
| 		for (uint32_t i = 0; i<noOfDims; i++) | ||||
| 		{ | ||||
| 			if(pDimensions[i] == 0) | ||||
| 			{ | ||||
| 				POLYVOX_THROW(std::out_of_range, "Invalid array dimension"); | ||||
| 			} | ||||
| 			POLYVOX_THROW_IF(pDimensions[i] == 0, std::out_of_range, "Invalid array dimension"); | ||||
|  | ||||
| 			m_uNoOfElements *= pDimensions[i]; | ||||
| 			m_pDimensions[i] = pDimensions[i]; | ||||
| @@ -197,10 +188,7 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	uint32_t Array<noOfDims, ElementType>::getDimension(uint32_t uDimension) | ||||
| 	{ | ||||
| 		if(uDimension >= noOfDims) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array dimension out of range"); | ||||
| 		} | ||||
| 		POLYVOX_THROW_IF(uDimension >= noOfDims, std::out_of_range, "Array dimension out of range"); | ||||
|  | ||||
| 		return m_pDimensions[uDimension]; | ||||
| 	} | ||||
| @@ -266,10 +254,7 @@ namespace PolyVox | ||||
| 	template <typename ElementType> | ||||
| 	ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) | ||||
| 	{ | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
| 		POLYVOX_THROW_IF(uIndex >= m_pDimensions[0], std::out_of_range, "Array index out of range"); | ||||
|  | ||||
| 		return m_pElements[uIndex]; | ||||
| 	} | ||||
| @@ -277,10 +262,7 @@ namespace PolyVox | ||||
| 	template <typename ElementType> | ||||
| 	const ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) const | ||||
| 	{ | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
| 		POLYVOX_THROW_IF(uIndex >= m_pDimensions[0], std::out_of_range, "Array index out of range"); | ||||
|  | ||||
| 		return m_pElements[uIndex]; | ||||
| 	} | ||||
|   | ||||
| @@ -36,16 +36,23 @@ namespace PolyVox | ||||
| 	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// More details to come... | ||||
| 	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| 	 | ||||
| 	namespace WrapModes | ||||
| 	{ | ||||
| 		enum WrapMode | ||||
| 		{ | ||||
| 			Clamp = 0, | ||||
| 			Border = 1 | ||||
| 			Validate = 0, | ||||
| 			Clamp = 1, | ||||
| 			Border = 2, | ||||
| 			AssumeValid = 3 | ||||
| 		}; | ||||
| 	} | ||||
| 	typedef WrapModes::WrapMode WrapMode; | ||||
|  | ||||
| 	// Required for a trick to implement specialization of template member | ||||
| 	// functions in template classes. See http://stackoverflow.com/a/4951057 | ||||
| 	template <WrapMode W> struct WrapModeType{}; | ||||
|  | ||||
| 	template <typename _VoxelType> | ||||
| 	class BaseVolume | ||||
| 	{ | ||||
| @@ -109,7 +116,7 @@ namespace PolyVox | ||||
| 			inline VoxelType peekVoxel1px1py1pz(void) const; | ||||
|  | ||||
| 		protected: | ||||
| 			VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||
| 			VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||
|  | ||||
| 			DerivedVolumeType* mVolume; | ||||
|  | ||||
| @@ -146,22 +153,31 @@ namespace PolyVox | ||||
| 		int32_t getShortestSideLength(void) const; | ||||
| 		/// 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; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos) const; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) 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; | ||||
| 		VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) 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()) const; | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType()) const; | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) 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 | ||||
| 		void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// Sets the voxel at the position given by a 3D vector | ||||
| 		void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// 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 | ||||
| 		bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue); | ||||
|   | ||||
| @@ -154,26 +154,70 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \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 | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| @@ -201,30 +245,6 @@ 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 | ||||
| 	{ | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		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 | ||||
| 	{ | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param tBorder The value to use for voxels outside the volume. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -234,6 +254,28 @@ namespace PolyVox | ||||
| 		m_tBorderValue = tBorder; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \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 | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void BaseVolume<VoxelType>::setVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/) | ||||
| 	{ | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos the 3D position of the voxel | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void BaseVolume<VoxelType>::setVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/) | ||||
| 	{ | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param uXPos the \c x position of the voxel | ||||
| 	/// \param uYPos the \c y position of the voxel | ||||
|   | ||||
| @@ -57,7 +57,7 @@ namespace PolyVox | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxel(void) const | ||||
| 	{ | ||||
| 		return mVolume->getVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume); | ||||
| 		return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume, WrapModes::Validate); // FIXME - Use templatised version instead but watch for Linux compile errors. | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -154,63 +154,63 @@ namespace PolyVox | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume    , mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume    , mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume    , mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume    , mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume    , mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume    , mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -219,63 +219,63 @@ namespace PolyVox | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume - 1, mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume - 1, mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume - 1, mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume - 1, mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume - 1, mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume - 1, mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume    , mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume    , mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume    , mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume    , mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume    , mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume    , mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume + 1, mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume + 1, mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume + 1, mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume + 1, mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume    , mYPosInVolume + 1, mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume    , mYPosInVolume + 1, mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -284,100 +284,83 @@ namespace PolyVox | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume    , mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume    , mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume    , mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume    , mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume    , mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume    , mZPosInVolume + 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1nz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py0pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume    ); | ||||
| 		return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume    ); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <typename DerivedVolumeType> | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1pz(void) const | ||||
| 	{ | ||||
| 		return getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1); | ||||
| 		return getVoxelImpl(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 | ||||
| 	VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	{ | ||||
| 		if(mVolume->getEnclosingRegion().containsPoint(uXPos, uYPos, uZPos)) | ||||
| 		switch(m_eWrapMode) | ||||
| 		{ | ||||
| 			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 | ||||
| 					POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 				} | ||||
| 			} | ||||
| 		case WrapModes::Validate: | ||||
| 			return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Validate, m_tBorder); | ||||
| 		case WrapModes::Clamp: | ||||
| 			return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Clamp, m_tBorder); | ||||
| 		case WrapModes::Border: | ||||
| 			return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Border, m_tBorder); | ||||
| 		case WrapModes::AssumeValid: | ||||
| 			return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::AssumeValid, m_tBorder); | ||||
| 		default: | ||||
| 			// Should never happen | ||||
| 			POLYVOX_ASSERT(false, "Invalid wrap mode"); | ||||
| 			return VoxelType(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,83 +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_ConstVolumeProxy_H__ | ||||
| #define __PolyVox_ConstVolumeProxy_H__ | ||||
|  | ||||
| #include "PolyVoxCore/Region.h" | ||||
| #include "PolyVoxCore/Vector.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template <typename VoxelType> | ||||
| 	class ConstVolumeProxy | ||||
| 	{ | ||||
| 		//LargeVolume is a friend so it can call the constructor. | ||||
| 		friend class LargeVolume<VoxelType>; | ||||
| 	public: | ||||
| 		VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
| 			return m_pVolume.getVoxelAt(uXPos, uYPos, uZPos); | ||||
| 		} | ||||
|  | ||||
| 		VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(v3dPos), "Position is outside valid region"); | ||||
| 			return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); | ||||
| 		} | ||||
|  | ||||
| 		void setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
| 			m_pVolume.setVoxelAtConst(uXPos, uYPos, uZPos, tValue); | ||||
| 		} | ||||
|  | ||||
| 		void setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(v3dPos), "Position is outside valid region"); | ||||
| 			setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); | ||||
| 		} | ||||
| 	private: | ||||
| 		//Private constructor, so client code can't abuse this class. | ||||
| 		ConstVolumeProxy(const LargeVolume<VoxelType>& pVolume, const Region& regValid) | ||||
| 			:m_pVolume(pVolume) | ||||
| 			,m_regValid(regValid) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		//Private assignment operator, so client code can't abuse this class. | ||||
| 		ConstVolumeProxy& operator=(const ConstVolumeProxy& rhs) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		const LargeVolume<VoxelType>& m_pVolume; | ||||
| 		const Region& m_regValid; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #endif //__PolyVox_ConstVolumeProxy_H__ | ||||
| @@ -53,7 +53,7 @@ namespace PolyVox | ||||
|  | ||||
| 					uint32_t material = 0; | ||||
|  | ||||
| 					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)) | ||||
| 					if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(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))); | ||||
| @@ -63,7 +63,7 @@ namespace PolyVox | ||||
| 						m_meshCurrent->addTriangleCubic(v0,v2,v1); | ||||
| 						m_meshCurrent->addTriangleCubic(v1,v2,v3); | ||||
| 					} | ||||
| 					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)) | ||||
| 					if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x+1,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(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))); | ||||
| @@ -74,7 +74,7 @@ namespace PolyVox | ||||
| 						m_meshCurrent->addTriangleCubic(v1,v3,v2); | ||||
| 					} | ||||
|  | ||||
| 					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)) | ||||
| 					if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(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))); | ||||
| @@ -84,7 +84,7 @@ namespace PolyVox | ||||
| 						m_meshCurrent->addTriangleCubic(v0,v1,v2); | ||||
| 						m_meshCurrent->addTriangleCubic(v1,v3,v2); | ||||
| 					} | ||||
| 					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)) | ||||
| 					if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y+1,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(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))); | ||||
| @@ -95,7 +95,7 @@ namespace PolyVox | ||||
| 						m_meshCurrent->addTriangleCubic(v1,v2,v3); | ||||
| 					} | ||||
|  | ||||
| 					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)) | ||||
| 					if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(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))); | ||||
| @@ -105,7 +105,7 @@ namespace PolyVox | ||||
| 						m_meshCurrent->addTriangleCubic(v0,v2,v1); | ||||
| 						m_meshCurrent->addTriangleCubic(v1,v2,v3); | ||||
| 					} | ||||
| 					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)) | ||||
| 					if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z+1,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(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))); | ||||
|   | ||||
							
								
								
									
										132
									
								
								library/PolyVoxCore/include/PolyVoxCore/FilePager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								library/PolyVoxCore/include/PolyVoxCore/FilePager.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| /******************************************************************************* | ||||
| 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_FilePager_H__ | ||||
| #define __PolyVox_FilePager_H__ | ||||
|  | ||||
| #include "PolyVoxCore/Impl/TypeDef.h" | ||||
|  | ||||
| #include "PolyVoxCore/Pager.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <stdexcept> | ||||
| #include <string> | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	/** | ||||
| 	 * Provides an interface for performing paging of data. | ||||
| 	 */ | ||||
| 	template <typename VoxelType> | ||||
| 	class FilePager : public Pager<typename VoxelType> | ||||
| 	{ | ||||
| 	public: | ||||
| 		/// Constructor | ||||
| 		FilePager(const std::string& strFolderName) | ||||
| 			:Pager() | ||||
| 			,m_strFolderName(strFolderName) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		/// Destructor | ||||
| 		virtual ~FilePager() {}; | ||||
|  | ||||
| 		virtual void pageIn(const Region& region, Block<VoxelType>* pBlockData) | ||||
| 		{ | ||||
| 			POLYVOX_ASSERT(pBlockData, "Attempting to page in NULL block"); | ||||
| 			POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data"); | ||||
|  | ||||
| 			std::stringstream ss; | ||||
| 			ss << region.getLowerX() << "_" << region.getLowerY() << "_" << region.getLowerZ() << "_" | ||||
| 				 << region.getUpperX() << "_" << region.getUpperY() << "_" << region.getUpperZ(); | ||||
|  | ||||
| 			std::string filename = m_strFolderName + ss.str(); | ||||
|  | ||||
| 			// FIXME - This should be replaced by C++ style IO, but currently this causes problems with | ||||
| 			// the gameplay-cubiquity integration. See: https://github.com/blackberry/GamePlay/issues/919 | ||||
|  | ||||
| 			FILE* pFile = fopen(filename.c_str(), "rb"); | ||||
| 			if(pFile) | ||||
| 			{ | ||||
| 				logTrace() << "Paging in data for " << region; | ||||
|  | ||||
| 				fseek(pFile, 0L, SEEK_END); | ||||
| 				size_t fileSizeInBytes = ftell(pFile); | ||||
| 				fseek(pFile, 0L, SEEK_SET); | ||||
| 				 | ||||
| 				uint8_t* buffer = new uint8_t[fileSizeInBytes]; | ||||
| 				fread(buffer, sizeof(uint8_t), fileSizeInBytes, pFile); | ||||
| 				pBlockData->setCompressedData(buffer, fileSizeInBytes); | ||||
| 				delete[] buffer; | ||||
|  | ||||
| 				if(ferror(pFile)) | ||||
| 				{ | ||||
| 					POLYVOX_THROW(std::runtime_error, "Error reading in block data, even though a file exists."); | ||||
| 				} | ||||
|  | ||||
| 				fclose(pFile); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				logTrace() << "No data found for " << region << " during paging in."; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		virtual void pageOut(const Region& region, Block<VoxelType>* pBlockData) | ||||
| 		{ | ||||
| 			POLYVOX_ASSERT(pBlockData, "Attempting to page out NULL block"); | ||||
| 			POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data"); | ||||
|  | ||||
| 			logTrace() << "Paging out data for " << region; | ||||
|  | ||||
| 			std::stringstream ss; | ||||
| 			ss << region.getLowerX() << "_" << region.getLowerY() << "_" << region.getLowerZ() << "_" | ||||
| 				 << region.getUpperX() << "_" << region.getUpperY() << "_" << region.getUpperZ(); | ||||
|  | ||||
| 			std::string filename = m_strFolderName + ss.str(); | ||||
|  | ||||
| 			// FIXME - This should be replaced by C++ style IO, but currently this causes problems with | ||||
| 			// the gameplay-cubiquity integration. See: https://github.com/blackberry/GamePlay/issues/919 | ||||
|  | ||||
| 			FILE* pFile = fopen(filename.c_str(), "wb"); | ||||
| 			if(!pFile) | ||||
| 			{ | ||||
| 				POLYVOX_THROW(std::runtime_error, "Unable to open file to write out block data."); | ||||
| 			} | ||||
|  | ||||
| 			fwrite(pBlockData->getCompressedData(), sizeof(uint8_t), pBlockData->getCompressedDataLength(), pFile); | ||||
|  | ||||
| 			if(ferror(pFile)) | ||||
| 			{ | ||||
| 				POLYVOX_THROW(std::runtime_error, "Error writing out block data."); | ||||
| 			} | ||||
|  | ||||
| 			fclose(pFile); | ||||
| 		} | ||||
|  | ||||
| 	protected: | ||||
| 		std::string m_strFolderName; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #endif //__PolyVox_FilePager_H__ | ||||
| @@ -52,14 +52,14 @@ namespace PolyVox | ||||
| 		const int32_t z = volIter.getPosition().getZ(); | ||||
|  | ||||
| 		//FIXME - bitwise way of doing this? | ||||
| 		typename VolumeType::VoxelType voxel1nx = volIter.getVoxelAt(x-2, y  ,z  ) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1px = volIter.getVoxelAt(x-2, y  ,z  ) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1nx = volIter.getVoxel(x-2, y  ,z  ) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1px = volIter.getVoxel(x-2, y  ,z  ) > 0 ? 1: 0; | ||||
|  | ||||
| 		typename VolumeType::VoxelType voxel1ny = volIter.getVoxelAt(x  , y-2,z  ) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1py = volIter.getVoxelAt(x  , y-2,z  ) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1ny = volIter.getVoxel(x  , y-2,z  ) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1py = volIter.getVoxel(x  , y-2,z  ) > 0 ? 1: 0; | ||||
|  | ||||
| 		typename VolumeType::VoxelType voxel1nz = volIter.getVoxelAt(x  , y  ,z-2) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1pz = volIter.getVoxelAt(x  , y  ,z-2) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1nz = volIter.getVoxel(x  , y  ,z-2) > 0 ? 1: 0; | ||||
| 		typename VolumeType::VoxelType voxel1pz = volIter.getVoxel(x  , y  ,z-2) > 0 ? 1: 0; | ||||
|  | ||||
| 		return Vector3DFloat | ||||
| 		( | ||||
|   | ||||
| @@ -37,41 +37,36 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	class Block | ||||
| 	{ | ||||
| 		template <typename LengthType> | ||||
| 		struct RunlengthEntry | ||||
| 		{ | ||||
| 			LengthType length; | ||||
| 			VoxelType value; | ||||
|  | ||||
| 			//We can parametise the length on anything up to uint32_t. | ||||
| 			//This lets us experiment with the optimal size in the future. | ||||
| 			static uint32_t maxRunlength(void) {return (std::numeric_limits<LengthType>::max)();} | ||||
| 		}; | ||||
|  | ||||
| 	public: | ||||
| 		Block(uint16_t uSideLength = 0); | ||||
| 		Block(uint16_t uSideLength, Compressor* pCompressor); | ||||
|  | ||||
| 		const uint8_t* const getCompressedData(void) const; | ||||
| 		const uint32_t getCompressedDataLength(void) const; | ||||
| 		uint16_t getSideLength(void) const; | ||||
| 		VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const; | ||||
| 		VoxelType getVoxelAt(const Vector3DUint16& v3dPos) const; | ||||
| 		VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const; | ||||
| 		VoxelType getVoxel(const Vector3DUint16& v3dPos) const; | ||||
|  | ||||
| 		bool hasUncompressedData(void) const; | ||||
|  | ||||
| 		void setCompressedData(const uint8_t* const data, uint32_t dataLength); | ||||
| 		void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); | ||||
| 		void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); | ||||
|  | ||||
| 		void initialise(uint16_t uSideLength); | ||||
| 		void createUncompressedData(void); | ||||
| 		void destroyUncompressedData(void); | ||||
|  | ||||
| 		uint32_t calculateSizeInBytes(void); | ||||
|  | ||||
| 	public: | ||||
| 		void compress(Compressor* pCompressor); | ||||
| 		void uncompress(Compressor* pCompressor); | ||||
|  | ||||
| 		Compressor* m_pCompressor; | ||||
| 		uint8_t* m_pCompressedData; | ||||
| 		uint32_t m_uCompressedDataLength; | ||||
| 		VoxelType* m_tUncompressedData; | ||||
| 		uint16_t m_uSideLength; | ||||
| 		uint8_t m_uSideLengthPower;	 | ||||
| 		bool m_bIsCompressed; | ||||
| 		bool m_bIsUncompressedDataModified; | ||||
|  | ||||
| 		uint32_t timestamp; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -36,19 +36,56 @@ freely, subject to the following restrictions: | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template <typename VoxelType> | ||||
| 	Block<VoxelType>::Block(uint16_t uSideLength) | ||||
| 		:m_pCompressedData(0) | ||||
| 	Block<VoxelType>::Block(uint16_t uSideLength, Compressor* pCompressor) | ||||
| 		:m_pCompressor(pCompressor) | ||||
| 		,m_pCompressedData(0) | ||||
| 		,m_uCompressedDataLength(0) | ||||
| 		,m_tUncompressedData(0) | ||||
| 		,m_uSideLength(0) | ||||
| 		,m_uSideLengthPower(0) | ||||
| 		,m_bIsCompressed(false) | ||||
| 		,m_bIsUncompressedDataModified(true) | ||||
| 	{ | ||||
| 		if(uSideLength != 0) | ||||
| 		if(uSideLength == 0) | ||||
| 		{ | ||||
| 			initialise(uSideLength); | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Block side length cannot be zero."); | ||||
| 		} | ||||
|  | ||||
| 		if(!isPowerOf2(uSideLength)) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Block side length must be a power of two."); | ||||
| 		} | ||||
|  | ||||
| 		if(pCompressor == 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Block must be provided with a valid compressor."); | ||||
| 		} | ||||
|  | ||||
| 		//Compute the side length		 | ||||
| 		m_uSideLength = uSideLength; | ||||
| 		m_uSideLengthPower = logBase2(uSideLength); | ||||
|  | ||||
| 		//Temporarily create the block data. This is just so we can compress it an discard it. | ||||
| 		// FIXME - this is a temporary solution. | ||||
| 		const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength; | ||||
| 		m_tUncompressedData = new VoxelType[uNoOfVoxels];		 | ||||
| 		std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, VoxelType()); | ||||
| 		m_bIsUncompressedDataModified = true; | ||||
|  | ||||
| 		destroyUncompressedData(); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	const uint8_t* const Block<VoxelType>::getCompressedData(void) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL"); | ||||
| 		return m_pCompressedData; | ||||
| 	} | ||||
| 	 | ||||
| 	template <typename VoxelType> | ||||
| 	const uint32_t Block<VoxelType>::getCompressedDataLength(void) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL"); | ||||
| 		return m_uCompressedDataLength; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -58,12 +95,13 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType Block<VoxelType>::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const | ||||
| 	VoxelType Block<VoxelType>::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const | ||||
| 	{ | ||||
| 		// This is internal code not directly called by the user. For efficiency we assert rather than throwing. | ||||
| 		POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(hasUncompressedData(), "The block must have uncompressed data to call getVoxel()"); | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels."); | ||||
|  | ||||
| 		return m_tUncompressedData | ||||
| @@ -75,9 +113,28 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType Block<VoxelType>::getVoxelAt(const Vector3DUint16& v3dPos) const | ||||
| 	VoxelType Block<VoxelType>::getVoxel(const Vector3DUint16& v3dPos) const | ||||
| 	{ | ||||
| 		return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); | ||||
| 		return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	bool Block<VoxelType>::hasUncompressedData(void) const | ||||
| 	{ | ||||
| 		return m_tUncompressedData != 0; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::setCompressedData(const uint8_t* const data, uint32_t dataLength) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL"); | ||||
| 		POLYVOX_ASSERT(m_pCompressedData != data, "Attempting to copy data onto itself"); | ||||
|  | ||||
| 		delete[] m_pCompressedData; | ||||
|  | ||||
| 		m_uCompressedDataLength = dataLength; | ||||
| 		m_pCompressedData = new uint8_t[dataLength]; | ||||
| 		memcpy(m_pCompressedData, data, dataLength); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -87,6 +144,7 @@ namespace PolyVox | ||||
| 		POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(hasUncompressedData(), "The block must have uncompressed data to call setVoxelAt()"); | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels."); | ||||
|  | ||||
| 		m_tUncompressedData | ||||
| @@ -106,46 +164,11 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::initialise(uint16_t uSideLength) | ||||
| 	void Block<VoxelType>::destroyUncompressedData() | ||||
| 	{ | ||||
| 		//Release mode validation | ||||
| 		if(!isPowerOf2(uSideLength)) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Block side length must be a power of two."); | ||||
| 		} | ||||
|  | ||||
| 		//Compute the side length		 | ||||
| 		m_uSideLength = uSideLength; | ||||
| 		m_uSideLengthPower = logBase2(uSideLength); | ||||
|  | ||||
| 		//Create the block data | ||||
| 		m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength]; | ||||
|  | ||||
| 		//Clear it (should we bother?) | ||||
| 		const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength; | ||||
| 		std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, VoxelType()); | ||||
| 		m_bIsUncompressedDataModified = true; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t Block<VoxelType>::calculateSizeInBytes(void) | ||||
| 	{ | ||||
| 		//FIXME - This function is incomplete. | ||||
| 		uint32_t uSizeInBytes = sizeof(Block<VoxelType>); | ||||
| 		return  uSizeInBytes; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::compress(Compressor* pCompressor) | ||||
| 	{ | ||||
| 		if(m_bIsCompressed) | ||||
| 		if(!hasUncompressedData()) | ||||
| 		{  | ||||
| 			POLYVOX_THROW(invalid_operation, "Attempted to compress block which is already flagged as compressed."); | ||||
| 		} | ||||
|  | ||||
| 		if(!pCompressor) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "A valid compressor must be provided"); | ||||
| 			POLYVOX_THROW(invalid_operation, "No uncompressed data to compress."); | ||||
| 		} | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData != 0, "No uncompressed data is present."); | ||||
| @@ -169,7 +192,7 @@ namespace PolyVox | ||||
|  | ||||
| 			try | ||||
| 			{ | ||||
| 				uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
| 				uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
|  | ||||
| 				// Create new compressed data and copy across | ||||
| 				m_pCompressedData = new uint8_t[uCompressedLength]; | ||||
| @@ -181,7 +204,9 @@ namespace PolyVox | ||||
| 				// It is possible for the compression to fail. A common cause for this would be if the destination | ||||
| 				// buffer is not big enough. So now we try again using a buffer that is definitely big enough. | ||||
| 				// Note that ideally we will choose our earlier buffer size so that this almost never happens. | ||||
| 				uint32_t uMaxCompressedSize = pCompressor->getMaxCompressedSize(uSrcLength); | ||||
| 				logWarning() << "The compressor failed to compress the block, proabaly due to the buffer being too small."; | ||||
| 				logWarning() << "The compression will be tried again with a larger buffer"; | ||||
| 				uint32_t uMaxCompressedSize = m_pCompressor->getMaxCompressedSize(uSrcLength); | ||||
| 				uint8_t* buffer = new uint8_t[ uMaxCompressedSize ]; | ||||
|  | ||||
| 				pDstData = reinterpret_cast<void*>( buffer );				 | ||||
| @@ -189,7 +214,7 @@ namespace PolyVox | ||||
|  | ||||
| 				try | ||||
| 				{		 | ||||
| 					uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
| 					uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
|  | ||||
| 					// Create new compressed data and copy across | ||||
| 					m_pCompressedData = new uint8_t[uCompressedLength]; | ||||
| @@ -211,20 +236,14 @@ namespace PolyVox | ||||
| 		//Flag the uncompressed data as no longer being used. | ||||
| 		delete[] m_tUncompressedData; | ||||
| 		m_tUncompressedData = 0; | ||||
| 		m_bIsCompressed = true; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::uncompress(Compressor* pCompressor) | ||||
| 	void Block<VoxelType>::createUncompressedData() | ||||
| 	{ | ||||
| 		if(!m_bIsCompressed) | ||||
| 		if(hasUncompressedData()) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(invalid_operation, "Attempted to uncompress block which is not flagged as compressed."); | ||||
| 		} | ||||
|  | ||||
| 		if(!pCompressor) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "A valid compressor must be provided"); | ||||
| 			POLYVOX_THROW(invalid_operation, "Uncompressed data already exists."); | ||||
| 		} | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData == 0, "Uncompressed data already exists."); | ||||
| @@ -238,13 +257,20 @@ namespace PolyVox | ||||
|  | ||||
| 		//MinizCompressor compressor; | ||||
| 		//RLECompressor<VoxelType, uint16_t> compressor; | ||||
| 		uint32_t uUncompressedLength = pCompressor->decompress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
| 		uint32_t uUncompressedLength = m_pCompressor->decompress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
|  | ||||
| 		POLYVOX_ASSERT(uUncompressedLength == m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType), "Destination length has changed."); | ||||
|  | ||||
| 		//m_tUncompressedData = reinterpret_cast<VoxelType*>(uncompressedResult.ptr); | ||||
|  | ||||
| 		m_bIsCompressed = false; | ||||
| 		m_bIsUncompressedDataModified = false; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t Block<VoxelType>::calculateSizeInBytes(void) | ||||
| 	{ | ||||
| 		//FIXME - This function is incomplete. | ||||
| 		uint32_t uSizeInBytes = sizeof(Block<VoxelType>); | ||||
| 		return  uSizeInBytes; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -255,9 +255,36 @@ namespace PolyVox | ||||
|  * ... | ||||
|  */ | ||||
| #ifdef POLYVOX_THROW_ENABLED | ||||
|  | ||||
| 	#define POLYVOX_THROW_IF(condition, type, message) \ | ||||
| 		/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \ | ||||
| 		   but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \ | ||||
| 		   (http://stackoverflow.com/a/1946485) is to disable these warnings. */ \ | ||||
| 		POLYVOX_MSC_WARNING_PUSH \ | ||||
| 		POLYVOX_DISABLE_MSC_WARNING(4127) \ | ||||
| 		do \ | ||||
| 		{ \ | ||||
| 			if ((condition)) \ | ||||
| 			{ \ | ||||
| 				PolyVox::logError() << (message); \ | ||||
| 				throw type((message)); \ | ||||
| 			} \ | ||||
| 		} while(0) \ | ||||
| 		POLYVOX_MSC_WARNING_POP | ||||
|  | ||||
| 	#define POLYVOX_THROW(type, message) \ | ||||
| 		PolyVox::logError() << (message); \ | ||||
| 		throw type((message)) | ||||
| 		/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \ | ||||
| 		   but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \ | ||||
| 		   (http://stackoverflow.com/a/1946485) is to disable these warnings. */ \ | ||||
| 		POLYVOX_MSC_WARNING_PUSH \ | ||||
| 		POLYVOX_DISABLE_MSC_WARNING(4127) \ | ||||
| 		do \ | ||||
| 		{ \ | ||||
| 			PolyVox::logError() << (message); \ | ||||
| 			throw type((message)); \ | ||||
| 		} while(0) \ | ||||
| 		POLYVOX_MSC_WARNING_POP | ||||
|  | ||||
| #else | ||||
| 	namespace PolyVox | ||||
| 	{ | ||||
| @@ -267,10 +294,37 @@ namespace PolyVox | ||||
| 		void setThrowHandler(ThrowHandler newHandler); | ||||
| 	} | ||||
|  | ||||
| 	#define POLYVOX_THROW_IF(condition, type, message) \ | ||||
| 		/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \ | ||||
| 		   but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \ | ||||
| 		   (http://stackoverflow.com/a/1946485) is to disable these warnings. */ \ | ||||
| 		POLYVOX_MSC_WARNING_PUSH \ | ||||
| 		POLYVOX_DISABLE_MSC_WARNING(4127) \ | ||||
| 		do \ | ||||
| 		{ \ | ||||
| 			if ((condition)) \ | ||||
| 			{ \ | ||||
| 				PolyVox::logError() << (message); \ | ||||
| 				type except = (type)((message)); \ | ||||
| 				getThrowHandler()((except), __FILE__, __LINE__); \ | ||||
| 			} \ | ||||
| 		} while(0) \ | ||||
| 		POLYVOX_MSC_WARNING_POP | ||||
|  | ||||
| 	#define POLYVOX_THROW(type, message) \ | ||||
| 		PolyVox::logError() << (message); \ | ||||
| 		type except = (type)((message)); \ | ||||
| 		getThrowHandler()((except), __FILE__, __LINE__) | ||||
| 		/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \ | ||||
| 		   but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \ | ||||
| 		   (http://stackoverflow.com/a/1946485) is to disable these warnings. */ \ | ||||
| 		POLYVOX_MSC_WARNING_PUSH \ | ||||
| 		POLYVOX_DISABLE_MSC_WARNING(4127) \ | ||||
| 		do \ | ||||
| 		{ \ | ||||
| 			PolyVox::logError() << (message); \ | ||||
| 			type except = (type)((message)); \ | ||||
| 			getThrowHandler()((except), __FILE__, __LINE__); \ | ||||
| 		} while(0) \ | ||||
| 		POLYVOX_MSC_WARNING_POP | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace PolyVox | ||||
|   | ||||
| @@ -27,6 +27,7 @@ freely, subject to the following restrictions: | ||||
| #include "PolyVoxCore/BaseVolume.h" | ||||
| #include "Impl/Block.h" | ||||
| #include "PolyVoxCore/Compressor.h" | ||||
| #include "PolyVoxCore/Pager.h" | ||||
| #include "PolyVoxCore/Region.h" | ||||
| #include "PolyVoxCore/Vector.h" | ||||
|  | ||||
| @@ -41,8 +42,6 @@ freely, subject to the following restrictions: | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template <typename VoxelType> class ConstVolumeProxy; | ||||
|  | ||||
| 	/// The LargeVolume class provides a memory efficient method of storing voxel data while also allowing fast access and modification. | ||||
| 	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// A LargeVolume is essentially a 3D array in which each element (or <i>voxel</i>) is identified by a three dimensional (x,y,z) coordinate. | ||||
| @@ -227,62 +226,52 @@ namespace PolyVox | ||||
| 			VoxelType* mCurrentVoxel; | ||||
| 		}; | ||||
|  | ||||
| 		// Make the ConstVolumeProxy a friend | ||||
| 		friend class ConstVolumeProxy<VoxelType>; | ||||
|  | ||||
| 		struct LoadedBlock | ||||
| 		{ | ||||
| 		public: | ||||
| 			LoadedBlock(uint16_t uSideLength = 0) | ||||
| 				:block(uSideLength) | ||||
| 				,timestamp(0) | ||||
| 			{ | ||||
| 			} | ||||
|  | ||||
| 			Block<VoxelType> block; | ||||
| 			uint32_t timestamp; | ||||
| 		}; | ||||
| 		#endif | ||||
|  | ||||
| 	public:		 | ||||
| 		/// Constructor for creating a very large paging volume. | ||||
| 	public: | ||||
| 		/// Constructor for creating a fixed size volume. | ||||
| 		LargeVolume | ||||
| 		( | ||||
| 			polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler, | ||||
| 			polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler, | ||||
| 			uint16_t uBlockSideLength = 32 | ||||
| 			const Region& regValid, | ||||
| 			uint16_t uBlockSideLength = 32			 | ||||
| 		); | ||||
| 		/// Constructor for creating a fixed size volume. | ||||
| 		LargeVolume | ||||
| 		( | ||||
| 			const Region& regValid, | ||||
| 			Compressor* pCompressor = 0, | ||||
| 			polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler = 0, | ||||
| 			polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler = 0, | ||||
| 			bool bPagingEnabled = false, | ||||
| 			Compressor* pCompressor,	 | ||||
| 			Pager<VoxelType>* pPager ,	 | ||||
| 			uint16_t uBlockSideLength = 32 | ||||
| 		); | ||||
| 		/// Destructor | ||||
| 		~LargeVolume(); | ||||
|  | ||||
| 		/// 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; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos) const; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) 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; | ||||
| 		VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) 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()) const; | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType()) const; | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; | ||||
|  | ||||
| 		/// Sets the number of blocks for which uncompressed data is stored | ||||
| 		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 voxel at the position given by <tt>x,y,z</tt> coordinates | ||||
| 		void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// Sets the voxel at the position given by a 3D vector | ||||
| 		void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// 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 | ||||
| 		bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue); | ||||
| @@ -324,48 +313,47 @@ namespace PolyVox | ||||
| 				return false; | ||||
| 			} | ||||
| 		}; | ||||
| 		void initialise(const Region& regValidRegion, uint16_t uBlockSideLength); | ||||
| 		void initialise(); | ||||
|  | ||||
| 		/// gets called when a new region is allocated and needs to be filled | ||||
| 		/// NOTE: accessing ANY voxels outside this region during the process of this function | ||||
| 		/// is absolutely unsafe | ||||
| 		polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataRequiredHandler; | ||||
| 		/// gets called when a Region needs to be stored by the user, because LargeVolume will erase it right after | ||||
| 		/// this function returns | ||||
| 		/// NOTE: accessing ANY voxels outside this region during the process of this function | ||||
| 		/// is absolutely unsafe | ||||
| 		polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataOverflowHandler; | ||||
| 		// A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057 | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType tBorder) const; | ||||
| 	 | ||||
| 		Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) 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; | ||||
| 		void eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock) const; | ||||
|  | ||||
| 		//The block data | ||||
| 		mutable std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare> m_pBlocks; | ||||
| 		// The block data | ||||
| 		mutable std::map<Vector3DInt32, Block<VoxelType>, 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 | ||||
| 		//of blocks. However, this could mean the same block data is uncompressed and modified in more than one | ||||
| 		//location in memory... could be messy with threading. | ||||
| 		mutable std::vector< LoadedBlock* > m_vecUncompressedBlockCache; | ||||
| 		// 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 | ||||
| 		// of blocks. However, this could mean the same block data is uncompressed and modified in more than one | ||||
| 		// location in memory... could be messy with threading. | ||||
| 		mutable std::vector< Block<VoxelType>* > m_vecBlocksWithUncompressedData; | ||||
| 		mutable uint32_t m_uTimestamper; | ||||
| 		mutable Vector3DInt32 m_v3dLastAccessedBlockPos; | ||||
| 		mutable Block<VoxelType>* m_pLastAccessedBlock; | ||||
| 		uint32_t m_uMaxNumberOfUncompressedBlocks; | ||||
| 		uint32_t m_uMaxNumberOfBlocksInMemory; | ||||
|  | ||||
| 		//The size of the volume | ||||
| 		// The size of the volume | ||||
| 		Region m_regValidRegionInBlocks; | ||||
|  | ||||
| 		//The size of the blocks | ||||
| 		// The size of the blocks | ||||
| 		uint16_t m_uBlockSideLength; | ||||
| 		uint8_t m_uBlockSideLengthPower; | ||||
|  | ||||
| 		//The compressor used by the Blocks to compress their data if required. | ||||
| 		// The compressor used by the Blocks to compress their data if required. | ||||
| 		Compressor* m_pCompressor; | ||||
| 		Pager<VoxelType>* m_pPager; | ||||
|  | ||||
| 		bool m_bPagingEnabled; | ||||
| 		// Whether we created the compressor or whether it was provided | ||||
| 		// by the user. This controls whether we delete it on destruction. | ||||
| 		bool m_bIsOurCompressor; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -23,8 +23,7 @@ freely, subject to the following restrictions: | ||||
|  | ||||
| #include "PolyVoxCore/Impl/ErrorHandling.h" | ||||
|  | ||||
| //Included here rather than in the .h because it refers to LargeVolume (avoids forward declaration) | ||||
| #include "PolyVoxCore/ConstVolumeProxy.h" | ||||
| #include "PolyVoxCore/MinizCompressor.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| @@ -37,17 +36,19 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	LargeVolume<VoxelType>::LargeVolume | ||||
| 	( | ||||
| 		polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler, | ||||
| 		polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler, | ||||
| 		uint16_t uBlockSideLength | ||||
| 		const Region& regValid, | ||||
| 		uint16_t uBlockSideLength	 | ||||
| 	) | ||||
| 	:BaseVolume<VoxelType>(Region::MaxRegion) | ||||
| 	:BaseVolume<VoxelType>(regValid) | ||||
| 	{ | ||||
| 		m_funcDataRequiredHandler = dataRequiredHandler; | ||||
| 		m_funcDataOverflowHandler = dataOverflowHandler; | ||||
| 		m_bPagingEnabled = true; | ||||
| 		//Create a volume of the right size. | ||||
| 		initialise(Region::MaxRegion,uBlockSideLength); | ||||
| 		m_uBlockSideLength = uBlockSideLength; | ||||
|  | ||||
| 		m_pCompressor = new MinizCompressor(); | ||||
| 		m_bIsOurCompressor = true; | ||||
|  | ||||
| 		m_pPager = 0; | ||||
|  | ||||
| 		initialise(); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -64,20 +65,20 @@ namespace PolyVox | ||||
| 	( | ||||
| 		const Region& regValid, | ||||
| 		Compressor* pCompressor, | ||||
| 		polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler, | ||||
| 		polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler, | ||||
| 		bool bPagingEnabled, | ||||
| 		Pager<VoxelType>* pPager, | ||||
| 		uint16_t uBlockSideLength | ||||
| 	) | ||||
| 	:BaseVolume<VoxelType>(regValid) | ||||
| 	,m_pCompressor(pCompressor) | ||||
| 	{ | ||||
| 		m_funcDataRequiredHandler = dataRequiredHandler; | ||||
| 		m_funcDataOverflowHandler = dataOverflowHandler; | ||||
| 		m_bPagingEnabled = bPagingEnabled; | ||||
|  | ||||
| 		//Create a volume of the right size. | ||||
| 		initialise(regValid,uBlockSideLength); | ||||
| 		m_uBlockSideLength = uBlockSideLength; | ||||
|  | ||||
| 		m_pCompressor = pCompressor; | ||||
| 		m_bIsOurCompressor = false; | ||||
|  | ||||
| 		m_pPager = pPager; | ||||
|  | ||||
| 		initialise(); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -100,6 +101,12 @@ namespace PolyVox | ||||
| 	LargeVolume<VoxelType>::~LargeVolume() | ||||
| 	{ | ||||
| 		flushAll(); | ||||
|  | ||||
| 		// Only delete the compressor if it was created by us (in the constructor), not by the user. | ||||
| 		if(m_bIsOurCompressor) | ||||
| 		{ | ||||
| 			delete m_pCompressor; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -116,38 +123,83 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		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); | ||||
| 		// Simply call through to the real implementation | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<eWrapMode>(), tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); | ||||
| 		// Simply call through to the real implementation | ||||
| 		return getVoxel<eWrapMode>(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \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 | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		switch(eWrapMode) | ||||
| 		{ | ||||
| 		case WrapModes::Validate: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Validate>(), tBorder); | ||||
| 		case WrapModes::Clamp: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Clamp>(), tBorder); | ||||
| 		case WrapModes::Border: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Border>(), tBorder); | ||||
| 		case WrapModes::AssumeValid: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); | ||||
| 		default: | ||||
| 			// Should never happen | ||||
| 			POLYVOX_ASSERT(false, "Invalid wrap mode"); | ||||
| 			return VoxelType(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -171,7 +223,7 @@ namespace PolyVox | ||||
|  | ||||
| 			Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ); | ||||
|  | ||||
| 			return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset); | ||||
| 			return pUncompressedBlock->getVoxel(xOffset,yOffset,zOffset); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @@ -189,61 +241,6 @@ 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 | ||||
| 				POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \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); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// Increasing the size of the block cache will increase memory but may improve performance. | ||||
| 	/// You may want to set this to a large value (e.g. 1024) when you are first loading your | ||||
| @@ -272,6 +269,56 @@ namespace PolyVox | ||||
| 		m_uMaxNumberOfBlocksInMemory  = uMaxNumberOfBlocksInMemory; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \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 | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void LargeVolume<VoxelType>::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode) | ||||
| 	{ | ||||
| 		if((eWrapMode != WrapModes::Validate) && (eWrapMode != WrapModes::AssumeValid)) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Invalid wrap mode in call to setVoxel(). It must be 'None' or 'DontCheck'."); | ||||
| 		} | ||||
|  | ||||
| 		// This validation is skipped if the wrap mode is 'DontCheck' | ||||
| 		if(eWrapMode == WrapModes::Validate) | ||||
| 		{ | ||||
| 			if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) | ||||
| 			{ | ||||
| 				POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		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); | ||||
|  | ||||
| 		pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos the 3D position of the voxel | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void LargeVolume<VoxelType>::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode) | ||||
| 	{ | ||||
| 		setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue, eWrapMode); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param uXPos the \c x position of the voxel | ||||
| 	/// \param uYPos the \c y position of the voxel | ||||
| @@ -346,7 +393,7 @@ namespace PolyVox | ||||
| 				for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++) | ||||
| 				{ | ||||
| 					Vector3DInt32 pos(x,y,z); | ||||
| 					typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos); | ||||
| 					typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos); | ||||
| 					 | ||||
| 					if(itBlock != m_pBlocks.end()) | ||||
| 					{ | ||||
| @@ -377,7 +424,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void LargeVolume<VoxelType>::flushAll() | ||||
| 	{ | ||||
| 		typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i; | ||||
| 		typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator i; | ||||
| 		//Replaced the for loop here as the call to | ||||
| 		//eraseBlock was invalidating the iterator. | ||||
| 		while(m_pBlocks.size() > 0) | ||||
| @@ -411,7 +458,7 @@ namespace PolyVox | ||||
| 				for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++) | ||||
| 				{ | ||||
| 					Vector3DInt32 pos(x,y,z); | ||||
| 					typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos); | ||||
| 					typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos); | ||||
| 					if(itBlock == m_pBlocks.end()) | ||||
| 					{ | ||||
| 						// not loaded, not unloading | ||||
| @@ -434,44 +481,42 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void LargeVolume<VoxelType>::clearBlockCache(void) | ||||
| 	{ | ||||
| 		for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) | ||||
| 		for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++) | ||||
| 		{ | ||||
| 			m_vecUncompressedBlockCache[ct]->block.compress(m_pCompressor); | ||||
| 			m_vecBlocksWithUncompressedData[ct]->destroyUncompressedData(); | ||||
| 		} | ||||
| 		m_vecUncompressedBlockCache.clear(); | ||||
| 		m_vecBlocksWithUncompressedData.clear(); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This function should probably be made internal... | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void LargeVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength) | ||||
| 	void LargeVolume<VoxelType>::initialise() | ||||
| 	{		 | ||||
| 		//Validate parameters | ||||
| 		if(uBlockSideLength == 0) | ||||
| 		if(m_uBlockSideLength == 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Block side length cannot be zero."); | ||||
| 		} | ||||
| 		if(!isPowerOf2(uBlockSideLength)) | ||||
|  | ||||
| 		if(!isPowerOf2(m_uBlockSideLength)) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Block side length must be a power of two."); | ||||
| 		} | ||||
|  | ||||
| 		if(!m_pCompressor) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "You must provide a compressor for the LargeVolume to use."); | ||||
| 			POLYVOX_THROW(std::invalid_argument, "You must provide a valid compressor for the LargeVolume to use."); | ||||
| 		} | ||||
|  | ||||
| 		m_uTimestamper = 0; | ||||
| 		m_uMaxNumberOfUncompressedBlocks = 16; | ||||
| 		m_uBlockSideLength = uBlockSideLength; | ||||
| 		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; | ||||
|  | ||||
| 		this->m_regValidRegion = regValidRegion; | ||||
|  | ||||
| 		//Compute the block side length | ||||
| 		m_uBlockSideLength = uBlockSideLength; | ||||
| 		m_uBlockSideLengthPower = logBase2(m_uBlockSideLength); | ||||
|  | ||||
| 		m_regValidRegionInBlocks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uBlockSideLengthPower); | ||||
| @@ -496,63 +541,40 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock) const | ||||
| 	void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock) const | ||||
| 	{ | ||||
| 		if(m_funcDataOverflowHandler) | ||||
| 		if(itBlock->second.hasUncompressedData()) | ||||
| 		{ | ||||
| 			itBlock->second.destroyUncompressedData(); | ||||
| 		} | ||||
|  | ||||
| 		if(m_pPager) | ||||
| 		{ | ||||
| 			Vector3DInt32 v3dPos = itBlock->first; | ||||
| 			Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower); | ||||
| 			Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1); | ||||
|  | ||||
| 			Region reg(v3dLower, v3dUpper); | ||||
| 			ConstVolumeProxy<VoxelType> ConstVolumeProxy(*this, reg); | ||||
|  | ||||
| 			m_funcDataOverflowHandler(ConstVolumeProxy, reg); | ||||
| 			m_pPager->pageOut(reg, &(itBlock->second)); | ||||
| 		} | ||||
| 		if(m_pCompressor) | ||||
| 		 | ||||
| 		for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++) | ||||
| 		{ | ||||
| 			for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) | ||||
| 			// find the block in the uncompressed cache | ||||
| 			if(m_vecBlocksWithUncompressedData[ct] == &(itBlock->second)) | ||||
| 			{ | ||||
| 				// find the block in the uncompressed cache | ||||
| 				if(m_vecUncompressedBlockCache[ct] == &(itBlock->second)) | ||||
| 				{ | ||||
| 					// TODO: compression is unneccessary? or will not compressing this cause a memleak? | ||||
| 					itBlock->second.block.compress(m_pCompressor); | ||||
| 					// put last object in cache here | ||||
| 					m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back(); | ||||
| 					// decrease cache size by one since last element is now in here twice | ||||
| 					m_vecUncompressedBlockCache.resize(m_vecUncompressedBlockCache.size()-1); | ||||
| 					break; | ||||
| 				} | ||||
| 				// put last object in cache here | ||||
| 				m_vecBlocksWithUncompressedData[ct] = m_vecBlocksWithUncompressedData.back(); | ||||
| 				// decrease cache size by one since last element is now in here twice | ||||
| 				m_vecBlocksWithUncompressedData.resize(m_vecBlocksWithUncompressedData.size()-1); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		m_pBlocks.erase(itBlock); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	bool LargeVolume<VoxelType>::setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const | ||||
| 	{ | ||||
| 		//We don't have any range checks in this function because it | ||||
| 		//is a private function only called by the ConstVolumeProxy. The | ||||
| 		//ConstVolumeProxy takes care of ensuring the range is appropriate. | ||||
|  | ||||
| 		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 = uXPos - (blockX << m_uBlockSideLengthPower); | ||||
| 		const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); | ||||
| 		const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); | ||||
|  | ||||
| 		Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ); | ||||
|  | ||||
| 		pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue); | ||||
|  | ||||
| 		//Return true to indicate that we modified a voxel. | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	Block<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const | ||||
| 	{ | ||||
| @@ -564,25 +586,25 @@ namespace PolyVox | ||||
| 		//This check should also provide a significant speed boost as usually it is true. | ||||
| 		if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0)) | ||||
| 		{ | ||||
| 			POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data"); | ||||
| 			POLYVOX_ASSERT(m_pLastAccessedBlock->hasUncompressedData(), "Last accessed block has no uncompressed data."); | ||||
| 			return m_pLastAccessedBlock; | ||||
| 		}		 | ||||
|  | ||||
| 		typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(v3dBlockPos); | ||||
| 		typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(v3dBlockPos); | ||||
| 		// check whether the block is already loaded | ||||
| 		if(itBlock == m_pBlocks.end()) | ||||
| 		{ | ||||
| 			//The block is not in the map, so we will have to create a new block and add it. | ||||
| 			//Before we do so, we might want to dump some existing data to make space. We  | ||||
| 			//Only do this if paging is enabled. | ||||
| 			if(m_bPagingEnabled) | ||||
| 			if(m_pPager) | ||||
| 			{ | ||||
| 				// check wether another block needs to be unloaded before this one can be loaded | ||||
| 				if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory) | ||||
| 				{ | ||||
| 					// find the least recently used block | ||||
| 					typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i; | ||||
| 					typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itUnloadBlock = m_pBlocks.begin(); | ||||
| 					typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator i; | ||||
| 					typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itUnloadBlock = m_pBlocks.begin(); | ||||
| 					for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) | ||||
| 					{ | ||||
| 						if(i->second.timestamp < itUnloadBlock->second.timestamp) | ||||
| @@ -595,20 +617,17 @@ namespace PolyVox | ||||
| 			} | ||||
| 			 | ||||
| 			// create the new block | ||||
| 			LoadedBlock newBlock(m_uBlockSideLength); | ||||
| 			Block<VoxelType> newBlock(m_uBlockSideLength,  m_pCompressor); | ||||
|  | ||||
| 			// Blocks start out compressed - should we change this? | ||||
| 			// Or maybe we should just 'seed' them with compressed data, | ||||
| 			// rather than creating an empty block and then compressing? | ||||
| 			newBlock.block.compress(m_pCompressor); | ||||
|  | ||||
| 			itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first; | ||||
| 			auto retVal = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)); | ||||
| 			itBlock = retVal.first; | ||||
| 			POLYVOX_ASSERT(retVal.second == true, "Element was not supposed to exist!"); | ||||
|  | ||||
| 			//We have created the new block. If paging is enabled it should be used to | ||||
| 			//fill in the required data. Otherwise it is just left in the default state. | ||||
| 			if(m_bPagingEnabled) | ||||
| 			if(m_pPager) | ||||
| 			{ | ||||
| 				if(m_funcDataRequiredHandler) | ||||
| 				//if(m_funcDataRequiredHandler) | ||||
| 				{ | ||||
| 					// "load" will actually call setVoxel, which will in turn call this function again but the block will be found | ||||
| 					// so this if(itBlock == m_pBlocks.end()) never is entered		 | ||||
| @@ -616,26 +635,25 @@ namespace PolyVox | ||||
| 					Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower); | ||||
| 					Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1); | ||||
| 					Region reg(v3dLower, v3dUpper); | ||||
| 					ConstVolumeProxy<VoxelType> ConstVolumeProxy(*this, reg); | ||||
| 					m_funcDataRequiredHandler(ConstVolumeProxy, reg); | ||||
|  | ||||
| 					m_pPager->pageIn(reg, &(itBlock->second)); | ||||
| 				} | ||||
| 			} | ||||
| 		}		 | ||||
|  | ||||
| 		//Get the block and mark that we accessed it | ||||
| 		LoadedBlock& loadedBlock = itBlock->second; | ||||
| 		loadedBlock.timestamp = ++m_uTimestamper; | ||||
| 		Block<VoxelType>& block = itBlock->second; | ||||
| 		block.timestamp = ++m_uTimestamper; | ||||
| 		m_v3dLastAccessedBlockPos = v3dBlockPos; | ||||
| 		m_pLastAccessedBlock = &(loadedBlock.block); | ||||
| 		m_pLastAccessedBlock = █ | ||||
|  | ||||
| 		if(loadedBlock.block.m_bIsCompressed == false) | ||||
| 		if(block.hasUncompressedData()) | ||||
| 		{ 			 | ||||
| 			POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data"); | ||||
| 			return m_pLastAccessedBlock; | ||||
| 		} | ||||
|  | ||||
| 		//If we are allowed to compress then check whether we need to | ||||
| 		if((m_pCompressor) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks)) | ||||
| 		if(m_vecBlocksWithUncompressedData.size() == m_uMaxNumberOfUncompressedBlocks) | ||||
| 		{ | ||||
| 			int32_t leastRecentlyUsedBlockIndex = -1; | ||||
| 			uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)(); | ||||
| @@ -643,30 +661,30 @@ namespace PolyVox | ||||
| 			//Currently we find the oldest block by iterating over the whole array. Of course we could store the blocks sorted by | ||||
| 			//timestamp (set, priority_queue, etc) but then we'll need to move them around as the timestamp changes. Can come back  | ||||
| 			//to this if it proves to be a bottleneck (compraed to the cost of actually doing the compression/decompression). | ||||
| 			for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) | ||||
| 			for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++) | ||||
| 			{ | ||||
| 				if(m_vecUncompressedBlockCache[ct]->timestamp < uLeastRecentTimestamp) | ||||
| 				if(m_vecBlocksWithUncompressedData[ct]->timestamp < uLeastRecentTimestamp) | ||||
| 				{ | ||||
| 					uLeastRecentTimestamp = m_vecUncompressedBlockCache[ct]->timestamp; | ||||
| 					uLeastRecentTimestamp = m_vecBlocksWithUncompressedData[ct]->timestamp; | ||||
| 					leastRecentlyUsedBlockIndex = ct; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			//Compress the least recently used block. | ||||
| 			m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress(m_pCompressor); | ||||
| 			m_vecBlocksWithUncompressedData[leastRecentlyUsedBlockIndex]->destroyUncompressedData(); | ||||
|  | ||||
| 			//We don't actually remove any elements from this vector, we | ||||
| 			//simply change the pointer to point at the new uncompressed bloack.			 | ||||
| 			m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex] = &loadedBlock; | ||||
| 			m_vecBlocksWithUncompressedData[leastRecentlyUsedBlockIndex] = █ | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			m_vecUncompressedBlockCache.push_back(&loadedBlock); | ||||
| 			m_vecBlocksWithUncompressedData.push_back(&block); | ||||
| 		} | ||||
| 		 | ||||
| 		loadedBlock.block.uncompress(m_pCompressor); | ||||
| 		block.createUncompressedData(); | ||||
|  | ||||
| 		m_pLastAccessedBlock = &(loadedBlock.block); | ||||
| 		m_pLastAccessedBlock = &(block); | ||||
| 		POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data"); | ||||
| 		return m_pLastAccessedBlock; | ||||
| 	} | ||||
| @@ -691,19 +709,80 @@ namespace PolyVox | ||||
| 		uint32_t uSizeInBytes = sizeof(LargeVolume); | ||||
|  | ||||
| 		//Memory used by the blocks | ||||
| 		typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i; | ||||
| 		typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator i; | ||||
| 		for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) | ||||
| 		{ | ||||
| 			//Inaccurate - account for rest of loaded block. | ||||
| 			uSizeInBytes += i->second.block.calculateSizeInBytes(); | ||||
| 			uSizeInBytes += i->second.calculateSizeInBytes(); | ||||
| 		} | ||||
|  | ||||
| 		//Memory used by the block cache. | ||||
| 		uSizeInBytes += m_vecUncompressedBlockCache.capacity() * sizeof(LoadedBlock); | ||||
| 		uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType); | ||||
| 		uSizeInBytes += m_vecBlocksWithUncompressedData.capacity() * sizeof(Block<VoxelType>); | ||||
| 		uSizeInBytes += m_vecBlocksWithUncompressedData.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType); | ||||
|  | ||||
| 		return uSizeInBytes; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		// This function should never be called because one of the specialisations should always match. | ||||
| 		POLYVOX_ASSERT(false, "This function is not implemented and should never be called!"); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); | ||||
| 		} | ||||
|  | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		//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()); | ||||
|  | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) | ||||
| 		{ | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return tBorder; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType /*tBorder*/) const | ||||
| 	{ | ||||
| 		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->getVoxel(xOffset,yOffset,zOffset); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -88,7 +88,7 @@ namespace PolyVox | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return getVoxelAt(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); | ||||
| 			return getVoxelImpl(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -286,7 +286,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -296,7 +296,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -306,7 +306,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -316,7 +316,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -326,7 +326,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -336,7 +336,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -346,7 +346,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -356,7 +356,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -366,7 +366,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -378,7 +378,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -388,7 +388,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -398,7 +398,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -408,7 +408,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -418,7 +418,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *mCurrentVoxel; | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -428,7 +428,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -438,7 +438,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -448,7 +448,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -458,7 +458,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -470,7 +470,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -480,7 +480,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -490,7 +490,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -500,7 +500,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -510,7 +510,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -520,7 +520,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -530,7 +530,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -540,7 +540,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -550,7 +550,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -192,8 +192,8 @@ namespace PolyVox | ||||
| 			{ | ||||
| 				for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) | ||||
| 				{ | ||||
| 					AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y-1,z)); | ||||
| 					AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z)); | ||||
| 					AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y-1,z, WrapModes::Border)); | ||||
| 					AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border)); | ||||
|  | ||||
| 					satVolume.setVoxelAt(x,y,z,previousSum + currentSum); | ||||
| 				} | ||||
| @@ -206,8 +206,8 @@ namespace PolyVox | ||||
| 			{ | ||||
| 				for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) | ||||
| 				{ | ||||
| 					AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z-1)); | ||||
| 					AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z)); | ||||
| 					AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z-1, WrapModes::Border)); | ||||
| 					AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border)); | ||||
|  | ||||
| 					satVolume.setVoxelAt(x,y,z,previousSum + currentSum); | ||||
| 				} | ||||
| @@ -234,14 +234,14 @@ namespace PolyVox | ||||
| 					int32_t satUpperY = iSrcY + border; | ||||
| 					int32_t satUpperZ = iSrcZ + border; | ||||
|  | ||||
| 					AccumulationType a = satVolume.getVoxelAt(satLowerX,satLowerY,satLowerZ); | ||||
| 					AccumulationType b = satVolume.getVoxelAt(satUpperX,satLowerY,satLowerZ); | ||||
| 					AccumulationType c = satVolume.getVoxelAt(satLowerX,satUpperY,satLowerZ); | ||||
| 					AccumulationType d = satVolume.getVoxelAt(satUpperX,satUpperY,satLowerZ); | ||||
| 					AccumulationType e = satVolume.getVoxelAt(satLowerX,satLowerY,satUpperZ); | ||||
| 					AccumulationType f = satVolume.getVoxelAt(satUpperX,satLowerY,satUpperZ); | ||||
| 					AccumulationType g = satVolume.getVoxelAt(satLowerX,satUpperY,satUpperZ); | ||||
| 					AccumulationType h = satVolume.getVoxelAt(satUpperX,satUpperY,satUpperZ); | ||||
| 					AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ, WrapModes::Border); | ||||
| 					AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ, WrapModes::Border); | ||||
| 					AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ, WrapModes::Border); | ||||
| 					AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ, WrapModes::Border); | ||||
| 					AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ, WrapModes::Border); | ||||
| 					AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ, WrapModes::Border); | ||||
| 					AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ, WrapModes::Border); | ||||
| 					AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ, WrapModes::Border); | ||||
|  | ||||
| 					AccumulationType sum = h+c-d-g-f-a+b+e; | ||||
| 					uint32_t sideLength = border * 2 + 1; | ||||
|   | ||||
							
								
								
									
										49
									
								
								library/PolyVoxCore/include/PolyVoxCore/Pager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								library/PolyVoxCore/include/PolyVoxCore/Pager.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /******************************************************************************* | ||||
| 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_Pager_H__ | ||||
| #define __PolyVox_Pager_H__ | ||||
|  | ||||
| #include "PolyVoxCore/Impl/Block.h" | ||||
| #include "PolyVoxCore/Impl/TypeDef.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	/** | ||||
| 	 * Provides an interface for performing paging of data. | ||||
| 	 */ | ||||
| 	template <typename VoxelType> | ||||
| 	class Pager | ||||
| 	{ | ||||
| 	public: | ||||
| 		/// Constructor | ||||
| 		Pager() {}; | ||||
| 		/// Destructor | ||||
| 		virtual ~Pager() {}; | ||||
|  | ||||
| 		virtual void pageIn(const Region& region, Block<VoxelType>* pBlockData) = 0; | ||||
| 		virtual void pageOut(const Region& region, Block<VoxelType>* pBlockData) = 0; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #endif //__PolyVox_Pager_H__ | ||||
| @@ -116,18 +116,26 @@ namespace PolyVox | ||||
| 		~RawVolume(); | ||||
|  | ||||
| 		/// 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; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) 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()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType()) const; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) 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, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; | ||||
|  | ||||
| 		/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; | ||||
|  | ||||
| 		/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates | ||||
| 		void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// Sets the voxel at the position given by a 3D vector | ||||
| 		void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// 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 | ||||
| @@ -146,6 +154,14 @@ namespace PolyVox | ||||
| 	private: | ||||
| 		void initialise(const Region& regValidRegion); | ||||
|  | ||||
| 		// A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057 | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType tBorder) const; | ||||
|  | ||||
| 		//The block data | ||||
| 		VoxelType* m_pData; | ||||
| 	}; | ||||
|   | ||||
| @@ -74,38 +74,83 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		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() | ||||
| 		]; | ||||
| 		// Simply call through to the real implementation | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<eWrapMode>(), tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); | ||||
| 		// Simply call through to the real implementation | ||||
| 		return getVoxel<eWrapMode>(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \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 | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		switch(eWrapMode) | ||||
| 		{ | ||||
| 		case WrapModes::Validate: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Validate>(), tBorder); | ||||
| 		case WrapModes::Clamp: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Clamp>(), tBorder); | ||||
| 		case WrapModes::Border: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Border>(), tBorder); | ||||
| 		case WrapModes::AssumeValid: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); | ||||
| 		default: | ||||
| 			// Should never happen | ||||
| 			POLYVOX_ASSERT(false, "Invalid wrap mode"); | ||||
| 			return VoxelType(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -148,58 +193,53 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \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 | ||||
| 	/// \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 | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	void RawVolume<VoxelType>::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode) | ||||
| 	{ | ||||
| 		switch(eWrapMode) | ||||
| 		if((eWrapMode != WrapModes::Validate) && (eWrapMode != WrapModes::AssumeValid)) | ||||
| 		{ | ||||
| 			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()); | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Invalid wrap mode in call to setVoxel(). It must be 'None' or 'DontCheck'."); | ||||
| 		} | ||||
|  | ||||
| 				//Get the voxel value | ||||
| 				return getVoxel(uXPos, uYPos, uZPos); | ||||
| 				//No need to break as we've returned | ||||
| 			} | ||||
| 			case WrapModes::Border: | ||||
| 		// This validation is skipped if the wrap mode is 'DontCheck' | ||||
| 		if(eWrapMode == WrapModes::Validate) | ||||
| 		{ | ||||
| 			if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) | ||||
| 			{ | ||||
| 				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 | ||||
| 				POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 				POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		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(); | ||||
|  | ||||
| 		m_pData | ||||
| 		[ | ||||
| 			iLocalXPos +  | ||||
| 			iLocalYPos * this->getWidth() +  | ||||
| 			iLocalZPos * this->getWidth() * this->getHeight() | ||||
| 		] = tValue; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// \return The voxel value | ||||
| 	/// \param v3dPos the 3D position of the voxel | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	void RawVolume<VoxelType>::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode) | ||||
| 	{ | ||||
| 		return getVoxelWithWrapping(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); | ||||
| 		setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue, eWrapMode); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -285,5 +325,66 @@ namespace PolyVox | ||||
| 		return this->getWidth() * this->getHeight() * this->getDepth() * sizeof(VoxelType); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		// This function should never be called because one of the specialisations should always match. | ||||
| 		POLYVOX_ASSERT(false, "This function is not implemented and should never be called!"); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); | ||||
| 		} | ||||
|  | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		//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()); | ||||
|  | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) | ||||
| 		{ | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return tBorder; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType /*tBorder*/) const | ||||
| 	{ | ||||
| 		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() | ||||
| 		]; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -51,7 +51,7 @@ namespace PolyVox | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return getVoxelAt(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); | ||||
| 			return getVoxelImpl(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -229,7 +229,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -239,7 +239,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->getWidth()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -249,7 +249,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -259,7 +259,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -269,7 +269,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -279,7 +279,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -289,7 +289,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -299,7 +299,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->getWidth()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -309,7 +309,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -321,7 +321,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -331,7 +331,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->getWidth()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -341,7 +341,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -351,7 +351,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -361,7 +361,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *mCurrentVoxel; | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -371,7 +371,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -381,7 +381,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -391,7 +391,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->getWidth()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -401,7 +401,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -413,7 +413,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -423,7 +423,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->getWidth()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -433,7 +433,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -443,7 +443,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -453,7 +453,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -463,7 +463,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -473,7 +473,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -483,7 +483,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->getWidth()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -493,7 +493,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -157,6 +157,9 @@ namespace PolyVox | ||||
| 		/// Tests whether the given position is contained in the 'z' range of this Region. | ||||
| 		bool containsPointInZ(int32_t pos, int8_t boundary = 0) const; | ||||
|  | ||||
| 		/// Tests whether the given Region is contained in this Region. | ||||
| 		bool containsRegion(const Region& reg, 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. | ||||
|   | ||||
| @@ -155,18 +155,26 @@ namespace PolyVox | ||||
| 		~SimpleVolume(); | ||||
|  | ||||
| 		/// 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; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) 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()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType()) const; | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) 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, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; | ||||
|  | ||||
| 		/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||
| 		/// Gets a voxel at the position given by a 3D vector | ||||
| 		POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; | ||||
|  | ||||
| 		/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates | ||||
| 		void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// Sets the voxel at the position given by a 3D vector | ||||
| 		void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); | ||||
| 		/// 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 | ||||
| @@ -185,6 +193,14 @@ namespace PolyVox | ||||
| 	private:	 | ||||
| 		void initialise(const Region& regValidRegion, uint16_t uBlockSideLength); | ||||
|  | ||||
| 		// A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057 | ||||
| 		template <WrapMode eWrapMode> | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const; | ||||
| 		VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType tBorder) const; | ||||
|  | ||||
| 		Block* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const; | ||||
|  | ||||
| 		//The block data | ||||
|   | ||||
| @@ -74,38 +74,83 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		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); | ||||
| 		// Simply call through to the real implementation | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<eWrapMode>(), tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// This version of the function requires the wrap mode to be specified as a | ||||
| 	/// template parameter, which can provide better performance. | ||||
| 	/// \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 | ||||
| 	/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos) const | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); | ||||
| 		// Simply call through to the real implementation | ||||
| 		return getVoxel<eWrapMode>(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \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 | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		switch(eWrapMode) | ||||
| 		{ | ||||
| 		case WrapModes::Validate: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Validate>(), tBorder); | ||||
| 		case WrapModes::Clamp: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Clamp>(), tBorder); | ||||
| 		case WrapModes::Border: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Border>(), tBorder); | ||||
| 		case WrapModes::AssumeValid: | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); | ||||
| 		default: | ||||
| 			// Should never happen | ||||
| 			POLYVOX_ASSERT(false, "Invalid wrap mode"); | ||||
| 			return VoxelType(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This version of the function is provided so that the wrap mode does not need | ||||
| 	/// to be specified as a template parameter, as it may be confusing to some users. | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// \param tBorder The border value to use if the wrap mode is set to 'Border'. | ||||
| 	/// \return The voxel value | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -148,58 +193,53 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \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 | ||||
| 	/// \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 | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	void SimpleVolume<VoxelType>::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode) | ||||
| 	{ | ||||
| 		switch(eWrapMode) | ||||
| 		if((eWrapMode != WrapModes::Validate) && (eWrapMode != WrapModes::AssumeValid)) | ||||
| 		{ | ||||
| 			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()); | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Invalid wrap mode in call to setVoxel(). It must be 'None' or 'DontCheck'."); | ||||
| 		} | ||||
|  | ||||
| 				//Get the voxel value | ||||
| 				return getVoxel(uXPos, uYPos, uZPos); | ||||
| 				//No need to break as we've returned | ||||
| 			} | ||||
| 			case WrapModes::Border: | ||||
| 		// This validation is skipped if the wrap mode is 'DontCheck' | ||||
| 		if(eWrapMode == WrapModes::Validate) | ||||
| 		{ | ||||
| 			if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) | ||||
| 			{ | ||||
| 				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 | ||||
| 				POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 				POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		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 = uXPos - (blockX << m_uBlockSideLengthPower); | ||||
| 		const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); | ||||
| 		const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); | ||||
|  | ||||
| 		typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ); | ||||
|  | ||||
| 		pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param v3dPos The 3D position of the voxel | ||||
| 	/// \return The voxel value | ||||
| 	/// \param v3dPos the 3D position of the voxel | ||||
| 	/// \param tValue the value to which the voxel will be set | ||||
| 	/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. | ||||
| 	/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const | ||||
| 	void SimpleVolume<VoxelType>::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode) | ||||
| 	{ | ||||
| 		return getVoxelWithWrapping(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); | ||||
| 		setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue, eWrapMode); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -336,5 +376,66 @@ namespace PolyVox | ||||
| 		return uSizeInBytes; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	template <WrapMode eWrapMode> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		// This function should never be called because one of the specialisations should always match. | ||||
| 		POLYVOX_ASSERT(false, "This function is not implemented and should never be called!"); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); | ||||
| 		} | ||||
|  | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		//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()); | ||||
|  | ||||
| 		return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const | ||||
| 	{ | ||||
| 		if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) | ||||
| 		{ | ||||
| 			return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position. | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return tBorder; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType /*tBorder*/) const | ||||
| 	{ | ||||
| 		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); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -94,7 +94,7 @@ namespace PolyVox | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return getVoxelAt(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); | ||||
| 			return getVoxelImpl(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| @@ -305,7 +305,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -315,7 +315,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -325,7 +325,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -335,7 +335,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -345,7 +345,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -355,7 +355,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -365,7 +365,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -375,7 +375,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -385,7 +385,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -397,7 +397,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -407,7 +407,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -417,7 +417,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -427,7 +427,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -437,7 +437,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *mCurrentVoxel; | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -447,7 +447,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -457,7 +457,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -467,7 +467,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -477,7 +477,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -489,7 +489,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -499,7 +499,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -509,7 +509,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -519,7 +519,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -529,7 +529,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -539,7 +539,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -549,7 +549,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -559,7 +559,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -569,7 +569,7 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| 		return this->mVolume->getVoxelWithWrapping(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 		return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -107,7 +107,7 @@ namespace PolyVox | ||||
| 			{ | ||||
| 				for(int32_t sx = m_regSrc.getLowerX(), dx = m_regDst.getLowerX(); dx <= m_regDst.getUpperX(); sx++,dx++) | ||||
| 				{ | ||||
| 					const typename SrcVolumeType::VoxelType& tSrcVoxel = m_pVolSrc->getVoxelAt(sx,sy,sz); | ||||
| 					const typename SrcVolumeType::VoxelType& tSrcVoxel = m_pVolSrc->getVoxel(sx,sy,sz, WrapModes::AssumeValid); // FIXME use templatised version of getVoxel(), but watch out for Linux compile issues. | ||||
| 					const typename DstVolumeType::VoxelType& tDstVoxel = static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel); | ||||
| 					m_pVolDst->setVoxelAt(dx,dy,dz,tDstVoxel); | ||||
| 				} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user