Working to make compression handing more robust.

This commit is contained in:
Daviw Williams 2013-02-01 15:43:20 +01:00
parent 3d66db50e0
commit a5b768e5f9
7 changed files with 64 additions and 8 deletions

View File

@ -34,7 +34,14 @@ namespace PolyVox
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;
// Decompresses the data.
virtual uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0;
};
}

View File

@ -150,19 +150,52 @@ namespace PolyVox
if(m_bIsUncompressedDataModified)
{
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);
void* pDstData = 0;
uint32_t uCompressedLength = 0;
try
{
uint8_t buffer[1000000];
pDstData = reinterpret_cast<void*>( buffer );
uint32_t uDstLength = 1000000;
//MinizCompressor compressor;
//RLECompressor<VoxelType, uint16_t> compressor;
uint32_t uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength);
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] );
//Copy the data across
memcpy(m_pCompressedData, pDstData, uCompressedLength);
m_uCompressedDataLength = uCompressedLength;
delete pDstData;
}
//Flag the uncompressed data as no longer being used.

View File

@ -619,7 +619,9 @@ namespace PolyVox
// create the new block
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);
itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;

View File

@ -11,6 +11,7 @@ namespace PolyVox
MinizCompressor();
~MinizCompressor();
uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize);
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);
};

View File

@ -17,6 +17,7 @@ namespace PolyVox
RLECompressor();
~RLECompressor();
uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize);
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);
};

View File

@ -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>
uint32_t RLECompressor<ValueType, LengthType>::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
{

View File

@ -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)
{
mz_ulong ulDstLength = uDstLength;