Applying ker's patch unmodified.
This commit is contained in:
		| @@ -6,7 +6,6 @@ namespace PolyVox | ||||
| 	void smoothRegion(Volume<VoxelType>& volData, const Region& regionToSmooth) | ||||
| 	{ | ||||
| 		Region croppedRegion = regionToSmooth; | ||||
| 		croppedRegion.cropTo(volData.getEnclosingRegion()); | ||||
|  | ||||
| 		Array<3, uint16_t> temp(ArraySizes(croppedRegion.width())(croppedRegion.height())(croppedRegion.depth())); | ||||
|  | ||||
|   | ||||
| @@ -69,7 +69,9 @@ namespace PolyVox | ||||
| 		uint16_t m_uSideLength; | ||||
| 		uint8_t m_uSideLengthPower;	 | ||||
| 		bool m_bIsCompressed; | ||||
| 		bool m_bIsUncompressedDataModified;		 | ||||
| 		bool m_bIsUncompressedDataModified; | ||||
| 		uint32_t m_uTimestamp; | ||||
| 		uint32_t m_uUncompressedIndex; | ||||
| 		 | ||||
| 	}; | ||||
| } | ||||
|   | ||||
| @@ -36,9 +36,11 @@ namespace PolyVox | ||||
| 	Block<VoxelType>::Block(uint16_t uSideLength) | ||||
| 		:m_uSideLength(0) | ||||
| 		,m_uSideLengthPower(0) | ||||
| 		,m_tUncompressedData(0) | ||||
| 		,m_tUncompressedData(NULL) | ||||
| 		,m_bIsCompressed(true) | ||||
| 		,m_bIsUncompressedDataModified(true) | ||||
| 		,m_uTimestamp(0) | ||||
| 		,m_uUncompressedIndex((std::numeric_limits<uint32_t>::max)()) | ||||
| 	{ | ||||
| 		if(uSideLength != 0) | ||||
| 		{ | ||||
| @@ -103,14 +105,20 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::fill(VoxelType tValue) | ||||
| 	{ | ||||
| 		assert(m_tUncompressedData); | ||||
| 		if(!m_bIsCompressed) { | ||||
| 			//The memset *may* be faster than the std::fill(), but it doesn't compile nicely | ||||
| 			//in 64-bit mode as casting the pointer to an int causes a loss of precision. | ||||
| 			const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength; | ||||
| 			std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, tValue); | ||||
|  | ||||
| 		//The memset *may* be faster than the std::fill(), but it doesn't compile nicely | ||||
| 		//in 64-bit mode as casting the pointer to an int causes a loss of precision. | ||||
| 		const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength; | ||||
| 		std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, tValue); | ||||
|  | ||||
| 		m_bIsUncompressedDataModified = true; | ||||
| 			m_bIsUncompressedDataModified = true; | ||||
| 		} else { | ||||
| 			RunlengthEntry<uint16_t> rle; | ||||
| 			rle.length = m_uSideLength*m_uSideLength*m_uSideLength; | ||||
| 			rle.value = tValue; | ||||
| 			m_vecCompressedData.clear(); | ||||
| 			m_vecCompressedData.push_back(rle); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -128,6 +136,8 @@ namespace PolyVox | ||||
| 		//Compute the side length		 | ||||
| 		m_uSideLength = uSideLength; | ||||
| 		m_uSideLengthPower = logBase2(uSideLength); | ||||
|  | ||||
| 		Block<VoxelType>::fill(VoxelType()); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
|   | ||||
| @@ -32,6 +32,7 @@ freely, subject to the following restrictions: | ||||
| #include <set> | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include <functional> | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| @@ -115,33 +116,17 @@ namespace PolyVox | ||||
|  | ||||
| 		struct UncompressedBlock | ||||
| 		{ | ||||
| 			uint32_t uBlockIndex; | ||||
| 			Vector3DInt32 v3dBlockIndex; | ||||
| 			VoxelType* data; | ||||
|  | ||||
| 		}; | ||||
|  | ||||
| 	public:		 | ||||
| 		/// Constructor | ||||
| 		Volume(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength = 32); | ||||
| 		Volume(uint16_t uBlockSideLength = 32); | ||||
| 		/// Destructor | ||||
| 		~Volume();	 | ||||
| 		~Volume(); | ||||
|  | ||||
| 		/// Gets the value used for voxels which are outside the volume | ||||
| 		VoxelType getBorderValue(void) const; | ||||
| 		/// Gets a Region representing the extents of the Volume. | ||||
| 		Region getEnclosingRegion(void) const; | ||||
| 		/// Gets the width of the volume in voxels. | ||||
| 		int32_t getWidth(void) const; | ||||
| 		/// Gets the height of the volume in voxels. | ||||
| 		int32_t getHeight(void) const; | ||||
| 		/// Gets the depth of the volume in voxels. | ||||
| 		int32_t getDepth(void) const; | ||||
| 		/// Gets the length of the longest side in voxels | ||||
| 		int32_t getLongestSideLength(void) const; | ||||
| 		/// Gets the length of the shortest side in voxels | ||||
| 		int32_t getShortestSideLength(void) const; | ||||
| 		/// Gets the length of the diagonal in voxels | ||||
| 		float getDiagonalLength(void) const; | ||||
| 		/// Gets a voxel by <tt>x,y,z</tt> position | ||||
| 		VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||
| 		/// Gets a voxel by 3D vector position | ||||
| @@ -149,6 +134,8 @@ namespace PolyVox | ||||
|  | ||||
| 		/// Sets the number of blocks for which uncompressed data is stored. | ||||
| 		void setBlockCacheSize(uint16_t uBlockCacheSize); | ||||
| 		/// Sets the number of blocks which can be in memory before unload is called | ||||
| 		void setMaxBlocksLoaded(uint16_t uBlockCacheSize); | ||||
| 		/// Sets the value used for voxels which are outside the volume | ||||
| 		void setBorderValue(const VoxelType& tBorder); | ||||
| 		/// Sets the voxel at an <tt>x,y,z</tt> position | ||||
| @@ -159,15 +146,25 @@ namespace PolyVox | ||||
| 		void clearBlockCache(void); | ||||
| 		float calculateCompressionRatio(void); | ||||
| 		uint32_t calculateSizeInBytes(void); | ||||
| 		void useCompatibilityMode(void); | ||||
| 		/// Resizes the volume to the specified dimensions | ||||
| 		void resize(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength = 32); | ||||
|  | ||||
| 		void resize(uint16_t uBlockSideLength = 32); | ||||
| 		/// 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 | ||||
| 		std::function<void(const Volume<VoxelType>&, Region)> m_LoadCallback; | ||||
| 		/// this function can be called by m_LoadCallback without causing any weird effects | ||||
| 		bool load_setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const; | ||||
| 		/// gets called when a Region needs to be stored by the user, because Volume will erase it right after | ||||
| 		/// this function returns | ||||
| 		/// NOTE: accessing ANY voxels outside this region during the process of this function | ||||
| 		/// is absolutely unsafe | ||||
| 		std::function<void(const Volume<VoxelType>&, Region)> m_UnloadCallback; | ||||
| 	private: | ||||
| 		Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const; | ||||
| 		void eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const; | ||||
|  | ||||
| 		//The block data | ||||
| 		mutable std::vector< Block<VoxelType> > m_pBlocks; | ||||
| 		mutable std::map<Vector3DInt32, Block<VoxelType> > 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 | ||||
| @@ -176,8 +173,10 @@ namespace PolyVox | ||||
| 		mutable std::vector< UncompressedBlock > m_vecUncompressedBlockCache; | ||||
| 		mutable std::vector<uint32_t> m_pUncompressedTimestamps; | ||||
| 		mutable uint32_t m_uTimestamper; | ||||
| 		uint32_t m_ulastAccessedBlockIndex; | ||||
| 		mutable Vector3DInt32 m_v3dLastAccessedBlockPos; | ||||
| 		mutable Vector3DInt32 m_v3dLoadBlockPos; | ||||
| 		uint32_t m_uMaxUncompressedBlockCacheSize; | ||||
| 		uint32_t m_uMaxBlocksLoaded; | ||||
|  | ||||
| 		//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border | ||||
| 		//block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a | ||||
| @@ -185,22 +184,8 @@ namespace PolyVox | ||||
| 		//the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume. | ||||
| 		VoxelType* m_pUncompressedBorderData; | ||||
|  | ||||
| 		uint32_t m_uNoOfBlocksInVolume; | ||||
|  | ||||
| 		int32_t m_uWidthInBlocks; | ||||
| 		int32_t m_uHeightInBlocks; | ||||
| 		int32_t m_uDepthInBlocks; | ||||
|  | ||||
| 		int32_t m_uWidth; | ||||
| 		int32_t m_uHeight;	 | ||||
| 		int32_t m_uDepth; | ||||
|  | ||||
| 		uint8_t m_uBlockSideLengthPower; | ||||
| 		uint16_t m_uBlockSideLength; | ||||
|  | ||||
| 		int32_t m_uLongestSideLength; | ||||
| 		int32_t m_uShortestSideLength; | ||||
| 		float m_fDiagonalLength; | ||||
| 	}; | ||||
|  | ||||
| 	//Some handy typedefs | ||||
|   | ||||
| @@ -48,17 +48,19 @@ namespace PolyVox | ||||
| 	/// the default if you are not sure what to choose here. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	Volume<VoxelType>::Volume(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength) | ||||
| 		:m_uTimestamper(0) | ||||
| 	Volume<VoxelType>::Volume(uint16_t uBlockSideLength) | ||||
| 		: | ||||
| 		m_uTimestamper(0) | ||||
| 		,m_uMaxUncompressedBlockCacheSize(256) | ||||
| 		,m_uMaxBlocksLoaded(4096) | ||||
| 		,m_uBlockSideLength(uBlockSideLength) | ||||
| 		,m_pUncompressedBorderData(0) | ||||
| 		,m_ulastAccessedBlockIndex((std::numeric_limits<uint32_t>::max)()) //An invalid index | ||||
| 		,m_v3dLastAccessedBlockPos((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)()) //An invalid index | ||||
| 	{ | ||||
| 		setBlockCacheSize(m_uMaxUncompressedBlockCacheSize); | ||||
|  | ||||
| 		//Create a volume of the right size. | ||||
| 		resize(uWidth, uHeight, uDepth, uBlockSideLength); | ||||
| 		resize(uBlockSideLength); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -67,95 +69,10 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	Volume<VoxelType>::~Volume() | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// The border value is returned whenever an atempt is made to read a voxel which | ||||
| 	/// is outside the extents of the volume. | ||||
| 	/// \return The value used for voxels outside of the volume | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType Volume<VoxelType>::getBorderValue(void) const | ||||
| 	{ | ||||
| 		/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(const_cast<Block<VoxelType>*>(&m_pBorderBlock)); | ||||
| 		return pUncompressedBorderBlock->getVoxelAt(0,0,0);*/ | ||||
| 		return *m_pUncompressedBorderData; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// The result will always have a lower corner at (0,0,0) and an upper corner at one | ||||
| 	/// less than the side length. For example, if a volume has dimensions 256x512x1024 | ||||
| 	/// then the upper corner of the enclosing region will be at (255,511,1023). | ||||
| 	/// \return A Region representing the extent of the volume. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	Region Volume<VoxelType>::getEnclosingRegion(void) const | ||||
| 	{ | ||||
| 		return Region(Vector3DInt32(0,0,0), Vector3DInt32(m_uWidth-1,m_uHeight-1,m_uDepth-1)); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \return The width of the volume in voxels | ||||
| 	/// \sa getHeight(), getDepth() | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	int32_t Volume<VoxelType>::getWidth(void) const | ||||
| 	{ | ||||
| 		return m_uWidth; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \return The height of the volume in voxels | ||||
| 	/// \sa getWidth(), getDepth() | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	int32_t Volume<VoxelType>::getHeight(void) const | ||||
| 	{ | ||||
| 		return m_uHeight; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \return The depth of the volume in voxels | ||||
| 	/// \sa getWidth(), getHeight() | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	int32_t Volume<VoxelType>::getDepth(void) const | ||||
| 	{ | ||||
| 		return m_uDepth; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \return The length of the shortest side in voxels. For example, if a volume has | ||||
| 	/// dimensions 256x512x1024 this function will return 256. | ||||
| 	/// \sa getLongestSideLength(), getDiagonalLength() | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	int32_t Volume<VoxelType>::getShortestSideLength(void) const | ||||
| 	{ | ||||
| 		return m_uShortestSideLength; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \return The length of the longest side in voxels. For example, if a volume has | ||||
| 	/// dimensions 256x512x1024 this function will return 1024. | ||||
| 	/// \sa getShortestSideLength(), getDiagonalLength() | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	int32_t Volume<VoxelType>::getLongestSideLength(void) const | ||||
| 	{ | ||||
| 		return m_uLongestSideLength; | ||||
| 	}	 | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \return The length of the diagonal in voxels. For example, if a volume has | ||||
| 	/// dimensions 256x512x1024 this function will return sqrt(256*256+512*512+1024*1024) | ||||
| 	/// = 1173.139. This value is computed on volume creation so retrieving it is fast. | ||||
| 	/// \sa getShortestSideLength(), getLongestSideLength() | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	float Volume<VoxelType>::getDiagonalLength(void) const | ||||
| 	{ | ||||
| 		return m_fDiagonalLength; | ||||
| 		typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i; | ||||
| 		for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i = m_pBlocks.begin()) { | ||||
| 			eraseBlock(i); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -167,26 +84,17 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType Volume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	{ | ||||
| 		//We don't use getEnclosingRegion here because we care | ||||
| 		//about speed | ||||
| 		if((uXPos >=0) && (uYPos >=0) && (uZPos >=0) && (uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth())) | ||||
| 		{ | ||||
| 			const int32_t blockX = uXPos >> m_uBlockSideLengthPower; | ||||
| 			const int32_t blockY = uYPos >> m_uBlockSideLengthPower; | ||||
| 			const int32_t blockZ = uZPos >> m_uBlockSideLengthPower; | ||||
| 		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); | ||||
| 		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); | ||||
| 		Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ); | ||||
|  | ||||
| 			return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return getBorderValue(); | ||||
| 		} | ||||
| 		return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -214,14 +122,27 @@ namespace PolyVox | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// \param tBorder The value to use for voxels outside the volume. | ||||
| 	/// Increasing the number of blocks in memory causes fewer calls to load/unload | ||||
| 	/// \param uMaxBlocks The number of blocks | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void Volume<VoxelType>::setBorderValue(const VoxelType& tBorder)  | ||||
| 	void Volume<VoxelType>::setMaxBlocksLoaded(uint16_t uMaxBlocks) | ||||
| 	{ | ||||
| 		/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock); | ||||
| 		return pUncompressedBorderBlock->fill(tBorder);*/ | ||||
| 		std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder); | ||||
| 		if(uMaxBlocks < m_pBlocks.size()) { | ||||
| 			std::cout << uMaxBlocks << ", " << m_pBlocks.size() << ", " << m_pBlocks.size() - uMaxBlocks << std::endl; | ||||
| 			// we need to unload some blocks | ||||
| 			for(int j = 0; j < m_pBlocks.size() - uMaxBlocks; j++) { | ||||
| 				typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i; | ||||
| 				typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itUnloadBlock = m_pBlocks.begin(); | ||||
| 				for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) { | ||||
| 					if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp) { | ||||
| 						itUnloadBlock = i; | ||||
| 					} | ||||
| 				} | ||||
| 				eraseBlock(itUnloadBlock); | ||||
| 			} | ||||
| 		} | ||||
| 		m_uMaxBlocksLoaded  = uMaxBlocks; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -234,30 +155,20 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	bool Volume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) | ||||
| 	{ | ||||
| 		//We don't use getEnclosingRegion here because we care | ||||
| 		//about speed | ||||
| 		if((uXPos >=0) && (uYPos >=0) && (uZPos >=0) && (uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth())) | ||||
| 		{ | ||||
| 			const int32_t blockX = uXPos >> m_uBlockSideLengthPower; | ||||
| 			const int32_t blockY = uYPos >> m_uBlockSideLengthPower; | ||||
| 			const int32_t blockZ = uZPos >> m_uBlockSideLengthPower; | ||||
| 		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); | ||||
| 		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); | ||||
| 		Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ); | ||||
|  | ||||
| 			pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue); | ||||
| 		pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue); | ||||
|  | ||||
| 			//Return true to indicate that we modified a voxel. | ||||
| 			return true; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			//Return false to indicate that no voxel was modified. | ||||
| 			return false; | ||||
| 		} | ||||
| 		//Return true to indicate that we modified a voxel. | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -276,7 +187,7 @@ namespace PolyVox | ||||
| 	{ | ||||
| 		for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) | ||||
| 		{ | ||||
| 			m_pBlocks[m_vecUncompressedBlockCache[ct].uBlockIndex].compress(); | ||||
| 			m_pBlocks[m_vecUncompressedBlockCache[ct].v3dBlockIndex].compress(); | ||||
| 			delete[] m_vecUncompressedBlockCache[ct].data; | ||||
| 		} | ||||
| 		m_vecUncompressedBlockCache.clear(); | ||||
| @@ -284,9 +195,6 @@ namespace PolyVox | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// Note: Calling this function will destroy all existing data in the volume. | ||||
| 	/// \param uWidth The desired width in voxels. This must be a power of two. | ||||
| 	/// \param uHeight The desired height in voxels. This must be a power of two. | ||||
| 	/// \param uDepth The desired depth in voxels. This must be a power of two. | ||||
| 	/// \param uBlockSideLength The size of the blocks which make up the volume. Small | ||||
| 	/// blocks are more likely to be homogeneous (so more easily shared) and have better | ||||
| 	/// cache behaviour. However, there is a memory overhead per block so if they are | ||||
| @@ -295,17 +203,11 @@ namespace PolyVox | ||||
| 	/// the default if you are not sure what to choose here. | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void Volume<VoxelType>::resize(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength) | ||||
| 	void Volume<VoxelType>::resize(uint16_t uBlockSideLength) | ||||
| 	{ | ||||
| 		//Debug mode validation | ||||
| 		assert(uBlockSideLength > 0); | ||||
| 		assert(isPowerOf2(uBlockSideLength)); | ||||
| 		assert(uBlockSideLength <= uWidth); | ||||
| 		assert(uBlockSideLength <= uHeight); | ||||
| 		assert(uBlockSideLength <= uDepth); | ||||
| 		assert(0 < uWidth); | ||||
| 		assert(0 < uHeight); | ||||
| 		assert(0 < uDepth); | ||||
|  | ||||
| 		//Release mode validation | ||||
| 		if(uBlockSideLength == 0) | ||||
| @@ -316,103 +218,112 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			throw std::invalid_argument("Block side length must be a power of two."); | ||||
| 		} | ||||
| 		if(uBlockSideLength > uWidth) | ||||
| 		{ | ||||
| 			throw std::invalid_argument("Block side length cannot be greater than volume width."); | ||||
| 		} | ||||
| 		if(uBlockSideLength > uHeight) | ||||
| 		{ | ||||
| 			throw std::invalid_argument("Block side length cannot be greater than volume height."); | ||||
| 		} | ||||
| 		if(uBlockSideLength > uDepth) | ||||
| 		{ | ||||
| 			throw std::invalid_argument("Block side length cannot be greater than volume depth."); | ||||
| 		} | ||||
| 		if(0 >= uWidth) | ||||
| 		{ | ||||
| 			throw std::invalid_argument("Volume width cannot be smaller than 1."); | ||||
| 		} | ||||
| 		if(0 >= uHeight) | ||||
| 		{ | ||||
| 			throw std::invalid_argument("Volume height cannot be smaller than 1."); | ||||
| 		} | ||||
| 		if(0 >= uDepth) | ||||
| 		{ | ||||
| 			throw std::invalid_argument("Volume depth cannot be smaller than 1."); | ||||
| 		} | ||||
|  | ||||
| 		//Clear the previous data | ||||
| 		m_pBlocks.clear(); | ||||
| 		m_pUncompressedTimestamps.clear(); | ||||
|  | ||||
| 		//Compute the volume side lengths | ||||
| 		m_uWidth = uWidth; | ||||
| 		m_uHeight = uHeight; | ||||
| 		m_uDepth = uDepth; | ||||
| 		m_pUncompressedTimestamps.resize(m_uMaxUncompressedBlockCacheSize, 0); | ||||
|  | ||||
| 		//Compute the block side length | ||||
| 		m_uBlockSideLength = uBlockSideLength; | ||||
| 		m_uBlockSideLengthPower = logBase2(m_uBlockSideLength); | ||||
| 	} | ||||
|  | ||||
| 		//Compute the side lengths in blocks | ||||
| 		m_uWidthInBlocks = m_uWidth / m_uBlockSideLength; | ||||
| 		m_uHeightInBlocks = m_uHeight / m_uBlockSideLength; | ||||
| 		m_uDepthInBlocks = m_uDepth / m_uBlockSideLength; | ||||
| 	template <typename VoxelType> | ||||
| 	void Volume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const | ||||
| 	{ | ||||
| 		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); | ||||
| 		if(m_UnloadCallback) { | ||||
| 			m_UnloadCallback(std::ref(*this), reg); | ||||
| 		} | ||||
| 		m_pBlocks.erase(itBlock); | ||||
| 	} | ||||
|  | ||||
| 		//Compute number of blocks in the volume | ||||
| 		m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks; | ||||
|  | ||||
| 		//Create the blocks | ||||
| 		m_pBlocks.resize(m_uNoOfBlocksInVolume); | ||||
| 		for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i) | ||||
| 		{ | ||||
| 			m_pBlocks[i].initialise(m_uBlockSideLength); | ||||
| 	template <typename VoxelType> | ||||
| 	bool Volume<VoxelType>::load_setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const | ||||
| 	{ | ||||
| 		const int32_t blockX = uXPos >> m_uBlockSideLengthPower; | ||||
| 		const int32_t blockY = uYPos >> m_uBlockSideLengthPower; | ||||
| 		const int32_t blockZ = uZPos >> m_uBlockSideLengthPower; | ||||
| 		assert(blockX == m_v3dLoadBlockPos.getX()); | ||||
| 		assert(blockY == m_v3dLoadBlockPos.getY()); | ||||
| 		assert(blockZ == m_v3dLoadBlockPos.getZ()); | ||||
| 		if(blockX != m_v3dLoadBlockPos.getX() && blockY != m_v3dLoadBlockPos.getY() && blockZ != m_v3dLoadBlockPos.getZ()) { | ||||
| 			throw(std::invalid_argument("you are not allowed to write to any voxels outside the designated region")); | ||||
| 		} | ||||
|  | ||||
| 		m_pUncompressedTimestamps.resize(m_uNoOfBlocksInVolume); | ||||
| 		std::fill(m_pUncompressedTimestamps.begin(), m_pUncompressedTimestamps.end(), 0); | ||||
| 		const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower); | ||||
| 		const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); | ||||
| 		const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); | ||||
|  | ||||
| 		//Create the border block | ||||
| 		m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength]; | ||||
| 		std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType()); | ||||
| 		Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ); | ||||
|  | ||||
| 		//Other properties we might find useful later | ||||
| 		m_uLongestSideLength = (std::max)((std::max)(m_uWidth,m_uHeight),m_uDepth); | ||||
| 		m_uShortestSideLength = (std::min)((std::min)(m_uWidth,m_uHeight),m_uDepth); | ||||
| 		m_fDiagonalLength = sqrtf(static_cast<float>(m_uWidth * m_uWidth + m_uHeight * m_uHeight + m_uDepth * m_uDepth)); | ||||
| 		pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue); | ||||
|  | ||||
| 		//Return true to indicate that we modified a voxel. | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	Block<VoxelType>* Volume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const | ||||
| 	{ | ||||
| 		assert(uBlockX >= 0); | ||||
| 		assert(uBlockY >= 0); | ||||
| 		assert(uBlockZ >= 0); | ||||
| 		assert(uBlockX < m_uWidthInBlocks); | ||||
| 		assert(uBlockY < m_uHeightInBlocks); | ||||
| 		assert(uBlockZ < m_uDepthInBlocks); | ||||
| 		//Compute the block's index from it's position. | ||||
| 		const int32_t uBlockIndex = | ||||
| 				uBlockX +  | ||||
| 				uBlockY * m_uWidthInBlocks +  | ||||
| 				uBlockZ * m_uWidthInBlocks * m_uHeightInBlocks; | ||||
| 		assert(uBlockIndex < m_uNoOfBlocksInVolume); | ||||
| 		assert(uBlockIndex >= 0); | ||||
| 		Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ); | ||||
| 		typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock = m_pBlocks.find(v3dBlockPos); | ||||
| 		// check whether the block is already loaded | ||||
| 		if(itBlock == m_pBlocks.end()) { | ||||
| 			// it is not loaded | ||||
| 			// check wether another block needs to be unloaded before this one can be loaded | ||||
| 			if(m_pBlocks.size() == m_uMaxBlocksLoaded) { | ||||
| 				// find the least recently used block | ||||
| 				typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i; | ||||
| 				typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itUnloadBlock = m_pBlocks.begin(); | ||||
| 				for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) { | ||||
| 					if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp) { | ||||
| 						itUnloadBlock = i; | ||||
| 					} | ||||
| 				} | ||||
| 				eraseBlock(itUnloadBlock); | ||||
| 			} | ||||
| 			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); | ||||
| 			// create the new block | ||||
| 			m_pBlocks[v3dBlockPos] = Block<VoxelType>(m_uBlockSideLength); | ||||
| 			itBlock = m_pBlocks.find(v3dBlockPos); | ||||
| 			// fill it with data (well currently fill it with nothingness) | ||||
| 			// "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 | ||||
|  | ||||
| 			m_v3dLoadBlockPos = v3dBlockPos; | ||||
| 			if(m_LoadCallback) { | ||||
| 				m_LoadCallback(std::ref(*this), reg); | ||||
| 			} | ||||
| 			m_v3dLoadBlockPos = Vector3DInt32((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)()); | ||||
| 		} | ||||
|  | ||||
| 		//Get the block | ||||
| 		Block<VoxelType>* block = &(m_pBlocks[uBlockIndex]); | ||||
| 		Block<VoxelType>* block = &(itBlock->second); | ||||
|  | ||||
| 		//Check if we have the same block as last time, if so there's no need to even update | ||||
| 		//the time stamp. If we updated it everytime then that would be every time we touched | ||||
| 		//a voxel, which would overflow a uint32_t and require us to use a uint64_t instead. | ||||
| 		if(uBlockIndex == m_ulastAccessedBlockIndex) | ||||
| 		if(v3dBlockPos == m_v3dLastAccessedBlockPos) | ||||
| 		{ | ||||
| 			return block; | ||||
| 		} | ||||
| 		m_v3dLastAccessedBlockPos = v3dBlockPos; | ||||
|  | ||||
| 		m_pUncompressedTimestamps[uBlockIndex] = ++m_uTimestamper; | ||||
| 		m_uTimestamper++; | ||||
| 		block->m_uTimestamp = m_uTimestamper; | ||||
|  | ||||
| 		if(block->m_bIsCompressed == false) | ||||
| 		{  | ||||
| 			m_pUncompressedTimestamps[block->m_uUncompressedIndex] = m_uTimestamper; | ||||
| 			return block; | ||||
| 		} | ||||
|  | ||||
| @@ -427,28 +338,27 @@ namespace PolyVox | ||||
| 			uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)(); // you said not int64 ;) | ||||
| 			for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) | ||||
| 			{ | ||||
| 				if(m_pUncompressedTimestamps[m_vecUncompressedBlockCache[ct].uBlockIndex] < uLeastRecentTimestamp) | ||||
| 				if(m_pUncompressedTimestamps[ct] < uLeastRecentTimestamp) | ||||
| 				{ | ||||
| 					uLeastRecentTimestamp = m_pUncompressedTimestamps[m_vecUncompressedBlockCache[ct].uBlockIndex]; | ||||
| 					uLeastRecentTimestamp = m_pUncompressedTimestamps[ct]; | ||||
| 					leastRecentlyUsedBlockIndex = ct; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			uUncompressedBlockIndex = leastRecentlyUsedBlockIndex; | ||||
| 			m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex].compress(); | ||||
| 			m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex].m_tUncompressedData = 0; | ||||
| 			m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex = uBlockIndex; | ||||
| 			m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex].compress(); | ||||
| 			m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex = v3dBlockPos; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			UncompressedBlock uncompressedBlock; | ||||
| 			//uncompressedBlock.block = block; | ||||
| 			uncompressedBlock.uBlockIndex = uBlockIndex; | ||||
| 			uncompressedBlock.v3dBlockIndex = v3dBlockPos; | ||||
| 			uncompressedBlock.data = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength]; | ||||
| 			m_vecUncompressedBlockCache.push_back(uncompressedBlock); | ||||
| 			uUncompressedBlockIndex = m_vecUncompressedBlockCache.size() - 1; | ||||
| 		} | ||||
|  | ||||
| 		block->m_uUncompressedIndex = uUncompressedBlockIndex; | ||||
| 		block->uncompress(m_vecUncompressedBlockCache[uUncompressedBlockIndex].data); | ||||
|  | ||||
| 		return block; | ||||
| @@ -457,7 +367,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	float Volume<VoxelType>::calculateCompressionRatio(void) | ||||
| 	{ | ||||
| 		float fRawSize = m_uWidth * m_uHeight * m_uDepth * sizeof(VoxelType); | ||||
| 		float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType); | ||||
| 		float fCompressedSize = calculateSizeInBytes(); | ||||
| 		return fCompressedSize/fRawSize; | ||||
| 	} | ||||
| @@ -468,9 +378,9 @@ namespace PolyVox | ||||
| 		uint32_t uSizeInBytes = sizeof(Volume); | ||||
|  | ||||
| 		//Memory used by the blocks | ||||
| 		for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i) | ||||
| 		{ | ||||
| 			uSizeInBytes += m_pBlocks[i].calculateSizeInBytes(); | ||||
| 		typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i; | ||||
| 		for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) { | ||||
| 			i->second.calculateSizeInBytes(); | ||||
| 		} | ||||
|  | ||||
| 		//Memory used by the block cache. | ||||
| @@ -487,20 +397,4 @@ namespace PolyVox | ||||
| 		return uSizeInBytes; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void Volume<VoxelType>::useCompatibilityMode(void) | ||||
| 	{ | ||||
| 		setBlockCacheSize(m_uNoOfBlocksInVolume * 2); //Times two gives space to spare | ||||
|  | ||||
| 		for(int32_t z = 0; z < m_uDepthInBlocks; z++) | ||||
| 		{ | ||||
| 			for(int32_t y = 0; y < m_uHeightInBlocks; y++) | ||||
| 			{ | ||||
| 				for(int32_t x = 0; x < m_uWidthInBlocks; x++) | ||||
| 				{ | ||||
| 					getUncompressedBlock(x,y,z); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -26,6 +26,11 @@ freely, subject to the following restrictions: | ||||
| #include "Vector.h" | ||||
| #include "Region.h" | ||||
|  | ||||
| #define BORDER_LOW(x) ((( x >> mVolume->m_uBlockSideLengthPower) << mVolume->m_uBlockSideLengthPower) != x) | ||||
| #define BORDER_HIGH(x) ((( (x+1) >> mVolume->m_uBlockSideLengthPower) << mVolume->m_uBlockSideLengthPower) != (x+1)) | ||||
| //#define BORDER_LOW(x) (( x % mVolume->m_uBlockSideLength) != 0) | ||||
| //#define BORDER_HIGH(x) (( x % mVolume->m_uBlockSideLength) != mVolume->m_uBlockSideLength - 1) | ||||
|  | ||||
| #include <limits> | ||||
| namespace PolyVox | ||||
| { | ||||
| @@ -148,21 +153,9 @@ namespace PolyVox | ||||
| 				uYPosInBlock * mVolume->m_uBlockSideLength +  | ||||
| 				uZPosInBlock * mVolume->m_uBlockSideLength * mVolume->m_uBlockSideLength; | ||||
|  | ||||
| 		if((uXBlock < mVolume->m_uWidthInBlocks) && (uYBlock < mVolume->m_uHeightInBlocks) && (uZBlock < mVolume->m_uDepthInBlocks) && (uXBlock >= 0) && (uYBlock >= 0) && (uZBlock >=0)) | ||||
| 		{ | ||||
| 			const uint32_t uBlockIndexInVolume = uXBlock +  | ||||
| 				uYBlock * mVolume->m_uWidthInBlocks +  | ||||
| 				uZBlock * mVolume->m_uWidthInBlocks * mVolume->m_uHeightInBlocks; | ||||
| 			const Block<VoxelType>& currentBlock = mVolume->m_pBlocks[uBlockIndexInVolume]; | ||||
| 		Block<VoxelType>* pUncompressedCurrentBlock = mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock); | ||||
|  | ||||
| 			Block<VoxelType>* pUncompressedCurrentBlock = mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock); | ||||
|  | ||||
| 			mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			mCurrentVoxel = mVolume->m_pUncompressedBorderData + uVoxelIndexInBlock; | ||||
| 		} | ||||
| 		mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| @@ -264,7 +257,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny1nz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if(	BORDER_LOW(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -274,7 +267,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny0pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if(	BORDER_LOW(mXPosInVolume) && BORDER_LOW(mYPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -284,7 +277,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny1pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if(	BORDER_LOW(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -294,7 +287,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py1nz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if(	BORDER_LOW(mXPosInVolume) && BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -304,7 +297,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py0pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_LOW(mXPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1); | ||||
| 		} | ||||
| @@ -314,7 +307,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py1pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -324,7 +317,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py1nz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_LOW(mYPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -334,7 +327,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py0pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -344,7 +337,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py1pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -356,7 +349,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny1nz(void) const | ||||
| 	{ | ||||
| 		if((mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_LOW(mYPosInVolume) && BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -366,7 +359,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny0pz(void) const | ||||
| 	{ | ||||
| 		if((mYPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_LOW(mYPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -376,7 +369,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny1pz(void) const | ||||
| 	{ | ||||
| 		if((mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_LOW(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -386,7 +379,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px0py1nz(void) const | ||||
| 	{ | ||||
| 		if((mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -402,7 +395,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px0py1pz(void) const | ||||
| 	{ | ||||
| 		if((mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -412,7 +405,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py1nz(void) const | ||||
| 	{ | ||||
| 		if((mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_HIGH(mYPosInVolume) && BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -422,7 +415,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py0pz(void) const | ||||
| 	{ | ||||
| 		if((mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mYPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -432,7 +425,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py1pz(void) const | ||||
| 	{ | ||||
| 		if((mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -444,7 +437,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny1nz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -454,7 +447,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny0pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mYPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -464,7 +457,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny1pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -474,7 +467,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py1nz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -484,7 +477,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py0pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1); | ||||
| 		} | ||||
| @@ -494,7 +487,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py1pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -504,7 +497,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py1nz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_LOW(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -514,7 +507,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py0pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
| @@ -524,7 +517,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py1pz(void) const | ||||
| 	{ | ||||
| 		if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1)) | ||||
| 		if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) ) | ||||
| 		{ | ||||
| 			return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength); | ||||
| 		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user