Removed a lot of compression-related code.
This commit is contained in:
		| @@ -1,48 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 David Williams and Matthew 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_BlockCompressor_H__ | ||||
| #define __PolyVox_BlockCompressor_H__ | ||||
|  | ||||
| #include "PolyVoxCore/PolyVoxForwardDeclarations.h" | ||||
| #include "PolyVoxCore/CompressedBlock.h" | ||||
| #include "PolyVoxCore/UncompressedBlock.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	/** | ||||
| 	 * Provides an interface for performing compression of blocks. | ||||
| 	 */ | ||||
| 	template <typename VoxelType> | ||||
| 	class BlockCompressor | ||||
| 	{ | ||||
| 	public: | ||||
| 		BlockCompressor() {}; | ||||
| 		virtual ~BlockCompressor() {}; | ||||
|  | ||||
| 		virtual void compressData(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock) = 0; | ||||
| 		virtual void decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock) = 0; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #endif //__PolyVox_BlockCompressor_H__ | ||||
| @@ -1,63 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 David Williams and Matthew 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_CompressedBlock_H__ | ||||
| #define __PolyVox_CompressedBlock_H__ | ||||
|  | ||||
| #include "PolyVoxCore/Block.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template <typename VoxelType> | ||||
| 	class CompressedBlock : public Block<VoxelType> | ||||
| 	{ | ||||
| 		friend class LargeVolume<VoxelType>; | ||||
|  | ||||
| 	public: | ||||
| 		CompressedBlock(); | ||||
| 		~CompressedBlock(); | ||||
|  | ||||
| 		const uint8_t* getData(void) const; | ||||
| 		uint32_t getDataSizeInBytes(void) const; | ||||
|  | ||||
| 		void setData(const uint8_t* const pData, uint32_t uDataSizeInBytes); | ||||
|  | ||||
| 	private: | ||||
| 		/// Private copy constructor to prevent accisdental copying | ||||
| 		CompressedBlock(const CompressedBlock& /*rhs*/) {}; | ||||
|  | ||||
| 		/// Private assignment operator to prevent accisdental copying | ||||
| 		CompressedBlock& operator=(const CompressedBlock& /*rhs*/) {}; | ||||
|  | ||||
| 		// Made this private to avoid any confusion with getDataSizeInBytes(). | ||||
| 		// Users shouldn't really need this for CompressedBlock anyway. | ||||
| 		uint32_t calculateSizeInBytes(void); | ||||
|  | ||||
| 		uint8_t* m_pData; | ||||
| 		uint32_t m_uDataSizeInBytes; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #include "PolyVoxCore/CompressedBlock.inl" | ||||
|  | ||||
| #endif | ||||
| @@ -1,79 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 David Williams and Matthew Williams | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied | ||||
| warranty. In no event will the authors be held liable for any damages | ||||
| arising from the use of this software. | ||||
|  | ||||
| Permission is granted to anyone to use this software for any purpose, | ||||
| including commercial applications, and to alter it and redistribute it | ||||
| freely, subject to the following restrictions: | ||||
|  | ||||
|     1. The origin of this software must not be misrepresented; you must not | ||||
|     claim that you wrote the original software. If you use this software | ||||
|     in a product, an acknowledgment in the product documentation would be | ||||
|     appreciated but is not required. | ||||
|  | ||||
|     2. Altered source versions must be plainly marked as such, and must not be | ||||
|     misrepresented as being the original software. | ||||
|  | ||||
|     3. This notice may not be removed or altered from any source | ||||
|     distribution. 	 | ||||
| *******************************************************************************/ | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template <typename VoxelType> | ||||
| 	CompressedBlock<VoxelType>::CompressedBlock() | ||||
| 		:m_pData(0) | ||||
| 		,m_uDataSizeInBytes(0) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	CompressedBlock<VoxelType>::~CompressedBlock() | ||||
| 	{ | ||||
| 		delete[] m_pData; | ||||
| 		m_pData = 0; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	const uint8_t* CompressedBlock<VoxelType>::getData(void) const | ||||
| 	{ | ||||
| 		return m_pData; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t CompressedBlock<VoxelType>::getDataSizeInBytes(void) const | ||||
| 	{ | ||||
| 		return m_uDataSizeInBytes; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void CompressedBlock<VoxelType>::setData(const uint8_t* const pData, uint32_t uDataSizeInBytes) | ||||
| 	{ | ||||
| 		POLYVOX_THROW_IF(pData == 0, std::invalid_argument, "Pointer to data cannot be null"); | ||||
| 		POLYVOX_THROW_IF(m_pData == pData, std::invalid_argument, "Attempting to copy data onto itself"); | ||||
|  | ||||
| 		// Delete any existing data | ||||
| 		delete[] m_pData; | ||||
|  | ||||
| 		// Allocate new data | ||||
| 		m_uDataSizeInBytes = uDataSizeInBytes; | ||||
| 		m_pData = new uint8_t[uDataSizeInBytes]; | ||||
|  | ||||
| 		// Copy the data across | ||||
| 		memcpy(m_pData, pData, uDataSizeInBytes); | ||||
|  | ||||
| 		// Flag as modified | ||||
| 		this->m_bDataModified = true; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t CompressedBlock<VoxelType>::calculateSizeInBytes(void) | ||||
| 	{ | ||||
| 		// Returns the size of this class plus the size of the compressed data. | ||||
| 		uint32_t uSizeInBytes = sizeof(CompressedBlock<VoxelType>) + m_uDataSizeInBytes; | ||||
| 		return  uSizeInBytes; | ||||
| 	} | ||||
| } | ||||
| @@ -1,49 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 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_MinizWrapper_H__ | ||||
| #define __PolyVox_MinizWrapper_H__ | ||||
|  | ||||
| // The miniz library is suplied as a single '.c' file, but this is messy for a project like PolyVox | ||||
| // because it consists mostly of headers. Many of our headers may want to make use of Miniz code which | ||||
| // means we need to be careful about #including 'miniz.c' multiple times and getting linker errors. | ||||
| // We simplify this situation with this 'MinizWrapper.h' and 'MinizWrapper.c' which include 'miniz.c' | ||||
| // with only declarations and definitions respectively. 'MinizWrapper.cpp' only gets compiled once, | ||||
| // and all other parts of PolyVox can simply include 'MinizWrapper.h' to get the declarations. | ||||
|  | ||||
| // Diable things we don't need, and in particular the zlib compatible names which | ||||
| // would cause conflicts if a user application is using both PolyVox and zlib. | ||||
| //#define MINIZ_NO_STDIO | ||||
| //#define MINIZ_NO_ARCHIVE_APIS | ||||
| //#define MINIZ_NO_TIME | ||||
| //#define MINIZ_NO_ZLIB_APIS | ||||
| //#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES | ||||
| //#define MINIZ_NO_MALLOC | ||||
|  | ||||
| // Include only the declarations of the functions in miniz.c. Don't include | ||||
| // the actual definitions, as this 'MinizWrapper.h' may be included from multiple | ||||
| // locations and we want to avoid linker errors regarding multiple definitions. | ||||
| #define MINIZ_HEADER_FILE_ONLY | ||||
| #include "PolyVoxCore/Impl/miniz.c" | ||||
|  | ||||
| #endif //__PolyVox_MinizWrapper_H__ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -26,7 +26,6 @@ freely, subject to the following restrictions: | ||||
|  | ||||
| #include "PolyVoxCore/BaseVolume.h" | ||||
| #include "PolyVoxCore/Block.h" | ||||
| #include "PolyVoxCore/BlockCompressor.h" | ||||
| #include "PolyVoxCore/Pager.h" | ||||
| #include "PolyVoxCore/Region.h" | ||||
| #include "PolyVoxCore/Vector.h" | ||||
|   | ||||
| @@ -23,8 +23,6 @@ freely, subject to the following restrictions: | ||||
|  | ||||
| #include "PolyVoxCore/Impl/ErrorHandling.h" | ||||
|  | ||||
| #include "PolyVoxCore/MinizBlockCompressor.h" // For creating a default compressor when none is provided. | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| namespace PolyVox | ||||
|   | ||||
| @@ -1,65 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 David Williams and Matthew 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_MinizBlockCompressor_H__ | ||||
| #define __PolyVox_MinizBlockCompressor_H__ | ||||
|  | ||||
| #include "PolyVoxCore/BlockCompressor.h" | ||||
|  | ||||
| #include "PolyVoxCore/Impl/MinizWrapper.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	/** | ||||
| 	 * Provides an interface for performing paging of data. | ||||
| 	 */ | ||||
| 	template <typename VoxelType> | ||||
| 	class MinizBlockCompressor : public BlockCompressor<VoxelType> | ||||
| 	{ | ||||
| 	public: | ||||
| 		MinizBlockCompressor(int iCompressionLevel = 6); // Miniz defines MZ_DEFAULT_LEVEL = 6 so we use the same here | ||||
| 		~MinizBlockCompressor(); | ||||
|  | ||||
| 		void compressData(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock); | ||||
| 		void decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock); | ||||
|  | ||||
| 	public: | ||||
| 		uint32_t getExpectedCompressedSize(uint32_t uUncompressedInputSize); | ||||
| 		uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize); | ||||
| 		uint32_t compressWithMiniz(const void* pSrcData, size_t uSrcLength, void* pDstData, size_t uDstLength); | ||||
| 		uint32_t decompressWithMiniz(const void* pSrcData, size_t uSrcLength, void* pDstData, size_t uDstLength); | ||||
|  | ||||
| 		unsigned int m_uCompressionFlags; | ||||
|  | ||||
| 		// Data gets compressed into this, then we check how big the result | ||||
| 		// is and copy the required number of bytes to the destination block. | ||||
| 		std::vector<uint8_t> m_vecTempBuffer; | ||||
|  | ||||
| 		// tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k). | ||||
| 		tdefl_compressor* m_pDeflator; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #include "PolyVoxCore/MinizBlockCompressor.inl" | ||||
|  | ||||
| #endif //__PolyVox_MinizBlockCompressor_H__ | ||||
| @@ -1,210 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 David Williams and Matthew Williams | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied | ||||
| warranty. In no event will the authors be held liable for any damages | ||||
| arising from the use of this software. | ||||
|  | ||||
| Permission is granted to anyone to use this software for any purpose, | ||||
| including commercial applications, and to alter it and redistribute it | ||||
| freely, subject to the following restrictions: | ||||
|  | ||||
|     1. The origin of this software must not be misrepresented; you must not | ||||
|     claim that you wrote the original software. If you use this software | ||||
|     in a product, an acknowledgment in the product documentation would be | ||||
|     appreciated but is not required. | ||||
|  | ||||
|     2. Altered source versions must be plainly marked as such, and must not be | ||||
|     misrepresented as being the original software. | ||||
|  | ||||
|     3. This notice may not be removed or altered from any source | ||||
|     distribution. 	 | ||||
| *******************************************************************************/ | ||||
|  | ||||
| #include <sstream> | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	/** | ||||
| 	 * You can specify a compression level when constructing this compressor. This controls the tradeoff between speed and compression | ||||
| 	 * rate. Levels 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow). | ||||
| 	 * \param iCompressionLevel The desired compression level. | ||||
| 	 */ | ||||
| 	template <typename VoxelType> | ||||
| 	MinizBlockCompressor<VoxelType>::MinizBlockCompressor(int iCompressionLevel) | ||||
| 		:m_pDeflator(0) | ||||
| 	{ | ||||
| 		// Create and store the deflator. | ||||
| 		m_pDeflator = new tdefl_compressor; | ||||
|  | ||||
| 		// The number of dictionary probes to use at each compression level (0-10). 0=implies fastest/minimal possible probing. | ||||
| 		// The discontinuity is unsettling but may be explained by the 'iCompressionLevel <= 3' check later? | ||||
| 		static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 }; | ||||
|  | ||||
| 		// Create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). | ||||
| 		m_uCompressionFlags = TDEFL_WRITE_ZLIB_HEADER | s_tdefl_num_probes[(std::min)(10, iCompressionLevel)] | ((iCompressionLevel <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); | ||||
| 		if (!iCompressionLevel) | ||||
| 		{ | ||||
| 			m_uCompressionFlags |= TDEFL_FORCE_ALL_RAW_BLOCKS; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	MinizBlockCompressor<VoxelType>::~MinizBlockCompressor() | ||||
| 	{ | ||||
| 		// Delete the deflator | ||||
| 		delete m_pDeflator; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void MinizBlockCompressor<VoxelType>::compressData(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock) | ||||
| 	{ | ||||
| 		// The uncompressed data will be read straight out of the block | ||||
| 		void* pSrcData = reinterpret_cast<void*>(pSrcBlock->getData()); | ||||
| 		size_t uSrcLength = pSrcBlock->getDataSizeInBytes(); | ||||
|  | ||||
| 		// This compressor is expected to be used many times to compress a large number of blocks, but they are all | ||||
| 		// expected to have the same size. Therefore the resize() function below should only perform allocation once. | ||||
| 		uint32_t expectedCompressedSize = getExpectedCompressedSize(uSrcLength); | ||||
| 		if(m_vecTempBuffer.size() != expectedCompressedSize) | ||||
| 		{ | ||||
| 			POLYVOX_LOG_INFO("Resizing temp buffer to " << expectedCompressedSize << "bytes. " | ||||
| 				<< "This should only happen the first time the MinizBlockCompressor is used"); | ||||
| 			m_vecTempBuffer.resize(expectedCompressedSize); | ||||
| 		} | ||||
|  | ||||
| 		// The compressed data will be written into this temporary buffer. | ||||
| 		uint8_t* pDstData = &(m_vecTempBuffer[0]); | ||||
| 		size_t uDstLength = m_vecTempBuffer.size(); | ||||
|  | ||||
| 		try | ||||
| 		{ | ||||
| 			// Perform the compression | ||||
| 			uint32_t uCompressedLength = compressWithMiniz(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
|  | ||||
| 			// Copy the resulting compressed data into the compressed block | ||||
| 			pDstBlock->setData(pDstData, uCompressedLength);			 | ||||
| 		} | ||||
| 		catch(std::exception&) | ||||
| 		{ | ||||
| 			// 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. | ||||
| 			POLYVOX_LOG_WARNING("The compressor failed to compress the block, probabaly due to the buffer being too small."); | ||||
| 			POLYVOX_LOG_WARNING("The compression will be tried again with a larger buffer."); | ||||
|  | ||||
| 			std::vector<uint8_t> vecExtraBigBuffer; | ||||
| 			vecExtraBigBuffer.resize(getMaxCompressedSize(uSrcLength)); | ||||
|  | ||||
| 			uint8_t* pDstData = &(vecExtraBigBuffer[0]); | ||||
| 			size_t uDstLength = vecExtraBigBuffer.size(); | ||||
|  | ||||
| 			try | ||||
| 			{		 | ||||
| 				// Perform the compression | ||||
| 				uint32_t uCompressedLength = compressWithMiniz(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
|  | ||||
| 				// Copy the resulting compressed data into the compressed block | ||||
| 				pDstBlock->setData(pDstData, uCompressedLength); | ||||
| 			} | ||||
| 			catch(std::exception&) | ||||
| 			{ | ||||
| 				// At this point it didn't work even with a bigger buffer. | ||||
| 				// Not much more we can do so just rethrow the exception. | ||||
| 				POLYVOX_THROW(std::runtime_error, "Failed to compress block data"); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void MinizBlockCompressor<VoxelType>::decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock) | ||||
| 	{ | ||||
| 		// Get raw pointers so that the data can be decompressed directly into the destination block. | ||||
| 		const void* pSrcData = reinterpret_cast<const void*>(pSrcBlock->getData()); | ||||
| 		void* pDstData = reinterpret_cast<void*>(pDstBlock->getData()); | ||||
| 		size_t uSrcLength = pSrcBlock->getDataSizeInBytes(); | ||||
| 		size_t uDstLength = pDstBlock->getDataSizeInBytes(); | ||||
|  | ||||
| 		// Perform the decompression | ||||
| 		uint32_t uUncompressedLength = decompressWithMiniz(pSrcData, uSrcLength, pDstData, uDstLength); | ||||
|  | ||||
| 		// We know we should have received exactly one block's worth of data. If not then something went wrong. | ||||
| 		POLYVOX_THROW_IF(uUncompressedLength != pDstBlock->getDataSizeInBytes(), std::runtime_error, "Decompressed data does not have the expected length"); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t MinizBlockCompressor<VoxelType>::getExpectedCompressedSize(uint32_t uUncompressedInputSize) | ||||
| 	{ | ||||
| 		// We expect this block compressor will be used for smoothly changing volume data such as density fields and so | ||||
| 		// the compression rate might not be great. The value beloew is basically a guess based on previous experience. | ||||
| 		uint32_t uExpectedCompressionRate = 4; | ||||
| 		return uUncompressedInputSize / uExpectedCompressionRate; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t MinizBlockCompressor<VoxelType>::getMaxCompressedSize(uint32_t uUncompressedInputSize) | ||||
| 	{ | ||||
| 		// The contents of this function are copied from miniz's 'mz_deflateBound()' | ||||
| 		// (which we can't use because it is part of the zlib-style higher level API). | ||||
| 		unsigned long source_len = uUncompressedInputSize; | ||||
|  | ||||
| 		// This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) | ||||
| 		return (std::max)(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t MinizBlockCompressor<VoxelType>::compressWithMiniz(const void* pSrcData, size_t uSrcLength, void* pDstData, size_t uDstLength) | ||||
| 	{ | ||||
| 		// It seems we have to reinitialise the deflator for each fresh dataset (it's probably intended for streaming, which we're not doing here) | ||||
| 		tdefl_status status = tdefl_init(m_pDeflator, NULL, NULL, m_uCompressionFlags); | ||||
| 		if (status != TDEFL_STATUS_OKAY) | ||||
| 		{ | ||||
| 			std::stringstream ss; | ||||
| 			ss << "tdefl_init() failed with return code '" << status << "'"; | ||||
| 			POLYVOX_THROW(std::runtime_error, ss.str()); | ||||
| 		} | ||||
|  | ||||
| 		// Compress as much of the input as possible (or all of it) to the output buffer. | ||||
| 		status = tdefl_compress(m_pDeflator, pSrcData, &uSrcLength, pDstData, &uDstLength, TDEFL_FINISH); | ||||
|  | ||||
| 		//Check whether the compression was successful. | ||||
| 		if (status != TDEFL_STATUS_DONE) | ||||
| 		{ | ||||
| 			std::stringstream ss; | ||||
| 			ss << "tdefl_compress() failed with return code '" << status << "'"; | ||||
| 			POLYVOX_THROW(std::runtime_error, ss.str()); | ||||
| 		} | ||||
|  | ||||
| 		// The compression modifies 'ulDstLength' to hold the new length. | ||||
| 		return uDstLength; | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	uint32_t MinizBlockCompressor<VoxelType>::decompressWithMiniz(const void* pSrcData, size_t uSrcLength, void* pDstData, size_t uDstLength) | ||||
| 	{ | ||||
| 		// I don't know exactly why this limitation exists but it's an implementation detail of miniz. It shouldn't matter for our purposes  | ||||
| 		// as our destination is a Block and those are always a power of two. If you need to use this code for other purposes then you'll | ||||
| 		// probably have to scale up your dst buffer to the nearest appropriate size. Alternatively you can use the mz_uncompress function, | ||||
| 		// but that means enabling parts of the miniz API which are #defined out at the top of this file. | ||||
| 		POLYVOX_THROW_IF(isPowerOf2(uDstLength) == false, std::invalid_argument, "Miniz decompressor requires the destination buffer to have a size which is a power of two."); | ||||
|  | ||||
| 		// Create and initialise the decompressor (I believe this is much small than the compressor). | ||||
| 		tinfl_decompressor inflator; | ||||
| 		tinfl_init(&inflator); | ||||
|  | ||||
| 		// Do the decompression. In some scenarios 'tinfl_decompress' would be called multiple times with the same dest buffer but | ||||
| 		// different locations within it. In our scenario it's only called once so the start and the location are the same (both pDstData). | ||||
| 		tinfl_status status = tinfl_decompress(&inflator, (const mz_uint8 *)pSrcData, &uSrcLength, (mz_uint8 *)pDstData, (mz_uint8 *)pDstData, &uDstLength, TINFL_FLAG_PARSE_ZLIB_HEADER); | ||||
|  | ||||
| 		//Check whether the decompression was successful. | ||||
| 		if (status != TINFL_STATUS_DONE) | ||||
| 		{ | ||||
| 			std::stringstream ss; | ||||
| 			ss << "tinfl_decompress() failed with return code '" << status << "'"; | ||||
| 			POLYVOX_THROW(std::runtime_error, ss.str()); | ||||
| 		} | ||||
|  | ||||
| 		// The decompression modifies 'ulDstLength' to hold the new length. | ||||
| 		return uDstLength; | ||||
| 	} | ||||
| } | ||||
| @@ -1,59 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 David Williams and Matthew 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_RLEBlockCompressor_H__ | ||||
| #define __PolyVox_RLEBlockCompressor_H__ | ||||
|  | ||||
| #include "PolyVoxCore/BlockCompressor.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template <typename VoxelType> | ||||
| 	class Run | ||||
| 	{ | ||||
| 	public: | ||||
| 		typedef uint16_t LengthType; | ||||
| 		VoxelType value; | ||||
| 		LengthType length; | ||||
| 	}; | ||||
|  | ||||
| 	/** | ||||
| 	 * Provides an interface for performing paging of data. | ||||
| 	 */ | ||||
| 	template <typename VoxelType> | ||||
| 	class RLEBlockCompressor : public BlockCompressor<VoxelType> | ||||
| 	{ | ||||
| 		 | ||||
|  | ||||
| 	public: | ||||
| 		RLEBlockCompressor(); | ||||
| 		~RLEBlockCompressor(); | ||||
|  | ||||
| 		void compressData(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock); | ||||
| 		void decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock); | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #include "PolyVoxCore/RLEBlockCompressor.inl" | ||||
|  | ||||
| #endif //__PolyVox_RLEBlockCompressor_H__ | ||||
| @@ -1,167 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2013 David Williams and Matthew Williams | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied | ||||
| warranty. In no event will the authors be held liable for any damages | ||||
| arising from the use of this software. | ||||
|  | ||||
| Permission is granted to anyone to use this software for any purpose, | ||||
| including commercial applications, and to alter it and redistribute it | ||||
| freely, subject to the following restrictions: | ||||
|  | ||||
|     1. The origin of this software must not be misrepresented; you must not | ||||
|     claim that you wrote the original software. If you use this software | ||||
|     in a product, an acknowledgment in the product documentation would be | ||||
|     appreciated but is not required. | ||||
|  | ||||
|     2. Altered source versions must be plainly marked as such, and must not be | ||||
|     misrepresented as being the original software. | ||||
|  | ||||
|     3. This notice may not be removed or altered from any source | ||||
|     distribution. 	 | ||||
| *******************************************************************************/ | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template <typename VoxelType> | ||||
| 	RLEBlockCompressor<VoxelType>::RLEBlockCompressor() | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	RLEBlockCompressor<VoxelType>::~RLEBlockCompressor() | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void RLEBlockCompressor<VoxelType>::compressData(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock) | ||||
| 	{ | ||||
| 		void* pSrcData = reinterpret_cast<void*>(pSrcBlock->getData()); | ||||
| 		uint32_t uSrcLength = pSrcBlock->getDataSizeInBytes(); | ||||
|  | ||||
| 		if(uSrcLength % sizeof(VoxelType) != 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::length_error, "Source length must be a integer multiple of the ValueType size"); | ||||
| 		} | ||||
|  | ||||
| 		// Lengths provided are in bytes, so convert them to be in terms of our types. | ||||
| 		uSrcLength /= sizeof(VoxelType); | ||||
| 		//uDstLength /= sizeof(Run); | ||||
|  | ||||
| 		// Get data pointers in the appropriate type | ||||
| 		const VoxelType* pSrcDataAsType = reinterpret_cast<const VoxelType*>(pSrcData); | ||||
| 		//Run* pDstDataAsRun = reinterpret_cast<Run*>(pDstData); | ||||
| 		std::vector< Run<VoxelType> > vecDstDataAsRuns; | ||||
|  | ||||
| 		// Pointers to just past the end of the data | ||||
| 		const VoxelType* pSrcDataEnd = pSrcDataAsType + uSrcLength; | ||||
| 		//Run* pDstDataEnd = pDstDataAsRun + uDstLength; | ||||
|  | ||||
| 		//Counter for the output length | ||||
| 		//uint32_t uDstLengthInBytes = 0; | ||||
|  | ||||
| 		// Read the first element of the source and set up the first run based on it. | ||||
| 		/*pDstDataAsRun->value = *pSrcDataAsType; | ||||
| 		pSrcDataAsType++; | ||||
| 		pDstDataAsRun->length = 1; | ||||
| 		uDstLengthInBytes += sizeof(Run);*/ | ||||
| 		Run<VoxelType> firstRun; | ||||
| 		firstRun.value = *pSrcDataAsType; | ||||
| 		firstRun.length = 1; | ||||
| 		vecDstDataAsRuns.push_back(firstRun); | ||||
|  | ||||
| 		pSrcDataAsType++; | ||||
|  | ||||
| 		//Now process all remaining elements of the source. | ||||
| 		while(pSrcDataAsType < pSrcDataEnd) | ||||
| 		{ | ||||
| 			// If the value is the same as the current run (and we have not | ||||
| 			// reached the maximum run length) then extend the current run. | ||||
| 			typename std::vector< Run< VoxelType> >::iterator currentRun = (vecDstDataAsRuns.end() - 1); | ||||
| 			if((*pSrcDataAsType == currentRun->value) && (currentRun->length < (std::numeric_limits<typename Run<VoxelType>::LengthType>::max)())) | ||||
| 			{ | ||||
| 				currentRun->length++; | ||||
| 			} | ||||
| 			// Otherwise we need to start a new Run. | ||||
| 			else | ||||
| 			{ | ||||
| 				/*pDstDataAsRun++; | ||||
|  | ||||
| 				// Check if we have enough space in the destination buffer. | ||||
| 				if(pDstDataAsRun >= pDstDataEnd) | ||||
| 				{ | ||||
| 					POLYVOX_THROW(std::runtime_error, "Insufficient space in destination buffer."); | ||||
| 				}*/ | ||||
|  | ||||
| 				// Create the new run. | ||||
| 				/*pDstDataAsRun->value = *pSrcDataAsType; | ||||
| 				pDstDataAsRun->length = 1; | ||||
| 				uDstLengthInBytes += sizeof(Run);*/ | ||||
|  | ||||
| 				Run<VoxelType> newRun; | ||||
| 				newRun.value = *pSrcDataAsType; | ||||
| 				newRun.length = 1; | ||||
| 				vecDstDataAsRuns.push_back(newRun); | ||||
| 			} | ||||
| 			 | ||||
| 			pSrcDataAsType++; | ||||
| 		} | ||||
|  | ||||
| 		//Now copy the data into the compressed block. | ||||
|  | ||||
| 		pDstBlock->setData(reinterpret_cast<uint8_t*>(&(vecDstDataAsRuns[0])), vecDstDataAsRuns.size() * sizeof(Run<VoxelType>)); | ||||
| 	} | ||||
|  | ||||
| 	template <typename VoxelType> | ||||
| 	void RLEBlockCompressor<VoxelType>::decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock) | ||||
| 	{ | ||||
| 		const void* pSrcData = reinterpret_cast<const void*>(pSrcBlock->getData()); | ||||
| 		uint32_t uSrcLength = pSrcBlock->getDataSizeInBytes(); | ||||
|  | ||||
| 		void* pDstData = pDstBlock->getData(); | ||||
| 		uint32_t uDstLength = pDstBlock->getDataSizeInBytes(); | ||||
|  | ||||
| 		if(uSrcLength % sizeof(Run<VoxelType>) != 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::length_error, "Source length must be a integer multiple of the Run size"); | ||||
| 		} | ||||
|  | ||||
| 		// Lengths provided are in bytes, so convert them to be in terms of our types. | ||||
| 		uSrcLength /= sizeof(Run<VoxelType>); | ||||
| 		uDstLength /= sizeof(VoxelType); | ||||
|  | ||||
| 		// Get data pointers in the appropriate type | ||||
| 		const Run<VoxelType>* pSrcDataAsRun = reinterpret_cast<const Run<VoxelType>*>(pSrcData); | ||||
| 		VoxelType* pDstDataAsType = reinterpret_cast<VoxelType*>(pDstData); | ||||
|  | ||||
| 		// Pointers to just past the end of the data | ||||
| 		const Run<VoxelType>* pSrcDataEnd = pSrcDataAsRun + uSrcLength; | ||||
| 		VoxelType* pDstDataEnd = pDstDataAsType + uDstLength; | ||||
|  | ||||
| 		//Counter for the output length | ||||
| 		uint32_t uDstLengthInBytes = 0; | ||||
|  | ||||
| 		while(pSrcDataAsRun < pSrcDataEnd) | ||||
| 		{ | ||||
| 			// Check if we have enough space in the destination buffer. | ||||
| 			if(pDstDataAsType + pSrcDataAsRun->length > pDstDataEnd) | ||||
| 			{ | ||||
| 				POLYVOX_THROW(std::runtime_error, "Insufficient space in destination buffer."); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
|  | ||||
| 			// Write the run into the destination | ||||
| 			std::fill(pDstDataAsType, pDstDataAsType + pSrcDataAsRun->length, pSrcDataAsRun->value); | ||||
| 			pDstDataAsType += pSrcDataAsRun->length; | ||||
|  | ||||
| 			uDstLengthInBytes += pSrcDataAsRun->length * sizeof(VoxelType);	 | ||||
| 			} | ||||
| 			pSrcDataAsRun++; | ||||
| 		} | ||||
|  | ||||
| 		POLYVOX_ASSERT(uDstLengthInBytes == pDstBlock->getDataSizeInBytes(), "Uncompressed data does not have the correct length."); | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user