Working to make compression handing more robust.
This commit is contained in:
		| @@ -34,7 +34,14 @@ namespace PolyVox | |||||||
| 		Compressor() {}; | 		Compressor() {}; | ||||||
| 		virtual ~Compressor() {}; | 		virtual ~Compressor() {}; | ||||||
|  |  | ||||||
|  | 		// Computes a worst-case scenario for how big the output can be for a given input size. If | ||||||
|  | 		// necessary you can use this as a destination buffer size, though it may be somewhat wasteful. | ||||||
|  | 		virtual uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize) = 0; | ||||||
|  |  | ||||||
|  | 		// Compresses the data. | ||||||
| 		virtual uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0; | 		virtual uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0; | ||||||
|  |  | ||||||
|  | 		// Decompresses the data. | ||||||
| 		virtual uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0; | 		virtual uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0; | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -150,19 +150,52 @@ namespace PolyVox | |||||||
| 		if(m_bIsUncompressedDataModified) | 		if(m_bIsUncompressedDataModified) | ||||||
| 		{ | 		{ | ||||||
| 			void* pSrcData = reinterpret_cast<void*>(m_tUncompressedData); | 			void* pSrcData = reinterpret_cast<void*>(m_tUncompressedData); | ||||||
| 			void* pDstData = reinterpret_cast<void*>( new uint8_t[1000000] ); |  | ||||||
| 			uint32_t uSrcLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType); | 			uint32_t uSrcLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType); | ||||||
|  |  | ||||||
|  | 			void* pDstData = 0; | ||||||
|  | 			uint32_t uCompressedLength = 0; | ||||||
|  |  | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				uint8_t buffer[1000000]; | ||||||
|  |  | ||||||
|  | 				pDstData = reinterpret_cast<void*>( buffer );				 | ||||||
| 				uint32_t uDstLength = 1000000; | 				uint32_t uDstLength = 1000000; | ||||||
|  |  | ||||||
| 			//MinizCompressor compressor; | 				uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||||
| 			//RLECompressor<VoxelType, uint16_t> compressor; | 			} | ||||||
| 			uint32_t uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); | 			catch(std::exception& e) | ||||||
|  | 			{ | ||||||
|  | 				// 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. | ||||||
|  | 				uint32_t uMaxCompressedSize = pCompressor->getMaxCompressedSize(uSrcLength); | ||||||
|  | 				uint8_t* buffer = new uint8_t[ uMaxCompressedSize ]; | ||||||
|  |  | ||||||
|  | 				pDstData = reinterpret_cast<void*>( buffer );				 | ||||||
|  | 				uint32_t uDstLength = uMaxCompressedSize; | ||||||
|  |  | ||||||
|  | 				try | ||||||
|  | 				{		 | ||||||
|  | 					uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); | ||||||
|  | 				} | ||||||
|  | 				catch(std::exception& e) | ||||||
|  | 				{ | ||||||
|  | 					// At this point it didn't work even with a bigger buffer. | ||||||
|  | 					// Not much more we can do so just rethrow the exception. | ||||||
|  | 					delete buffer; | ||||||
|  | 					POLYVOX_THROW(std::runtime_error, "Failed to compress block data"); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				delete buffer; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Delete the old compressed data and assign a new one | ||||||
|  | 			delete m_pCompressedData; | ||||||
| 			m_pCompressedData = reinterpret_cast<void*>( new uint8_t[uCompressedLength] ); | 			m_pCompressedData = reinterpret_cast<void*>( new uint8_t[uCompressedLength] ); | ||||||
|  |  | ||||||
|  | 			//Copy the data across | ||||||
| 			memcpy(m_pCompressedData, pDstData, uCompressedLength); | 			memcpy(m_pCompressedData, pDstData, uCompressedLength); | ||||||
| 			m_uCompressedDataLength = uCompressedLength; | 			m_uCompressedDataLength = uCompressedLength; | ||||||
|  |  | ||||||
| 			delete pDstData; |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		//Flag the uncompressed data as no longer being used. | 		//Flag the uncompressed data as no longer being used. | ||||||
|   | |||||||
| @@ -620,6 +620,8 @@ namespace PolyVox | |||||||
| 			LoadedBlock newBlock(m_uBlockSideLength); | 			LoadedBlock newBlock(m_uBlockSideLength); | ||||||
|  |  | ||||||
| 			// Blocks start out compressed - should we change this? | 			// 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); | 			newBlock.block.compress(m_pCompressor); | ||||||
|  |  | ||||||
| 			itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first; | 			itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first; | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ namespace PolyVox | |||||||
| 		MinizCompressor(); | 		MinizCompressor(); | ||||||
| 		~MinizCompressor(); | 		~MinizCompressor(); | ||||||
|  |  | ||||||
|  | 		uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize); | ||||||
| 		uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | 		uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | ||||||
| 		uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | 		uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | ||||||
| 	}; | 	}; | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ namespace PolyVox | |||||||
| 		RLECompressor(); | 		RLECompressor(); | ||||||
| 		~RLECompressor(); | 		~RLECompressor(); | ||||||
|  |  | ||||||
|  | 		uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize); | ||||||
| 		uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | 		uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | ||||||
| 		uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | 		uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); | ||||||
| 	}; | 	}; | ||||||
|   | |||||||
| @@ -14,6 +14,13 @@ namespace PolyVox | |||||||
| 	{ | 	{ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	template<typename ValueType, typename LengthType> | ||||||
|  | 	uint32_t RLECompressor<ValueType, LengthType>::getMaxCompressedSize(uint32_t uUncompressedInputSize) | ||||||
|  | 	{ | ||||||
|  | 		// In the worst case we will have a seperate Run (of length one) for each element of the input data. | ||||||
|  | 		return uUncompressedInputSize * sizeof(Run); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	template<typename ValueType, typename LengthType> | 	template<typename ValueType, typename LengthType> | ||||||
| 	uint32_t RLECompressor<ValueType, LengthType>::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) | 	uint32_t RLECompressor<ValueType, LengthType>::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -29,6 +29,11 @@ namespace PolyVox | |||||||
| 	{ | 	{ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	uint32_t MinizCompressor::getMaxCompressedSize(uint32_t uUncompressedInputSize) | ||||||
|  | 	{ | ||||||
|  | 		return static_cast<uint32_t>(mz_compressBound(static_cast<mz_ulong>(uUncompressedInputSize))); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	uint32_t MinizCompressor::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) | 	uint32_t MinizCompressor::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) | ||||||
| 	{ | 	{ | ||||||
| 		mz_ulong ulDstLength = uDstLength; | 		mz_ulong ulDstLength = uDstLength; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user