From 36676433bef9c595348e029b39d8267ef5b73dad Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Thu, 31 Jan 2013 15:54:04 +0100 Subject: [PATCH] Work on compression interface. --- library/PolyVoxCore/CMakeLists.txt | 1 + .../include/PolyVoxCore/Compressor.h | 42 +++++ .../include/PolyVoxCore/Impl/Block.h | 7 +- .../include/PolyVoxCore/Impl/Block.inl | 10 +- .../include/PolyVoxCore/LargeVolume.h | 5 + .../include/PolyVoxCore/LargeVolume.inl | 10 +- .../include/PolyVoxCore/MinizCompressor.h | 19 ++- .../include/PolyVoxCore/RLECompressor.h | 29 ++-- .../include/PolyVoxCore/RLECompressor.inl | 148 +++++++++--------- .../polyvoxcore/source/MinizCompressor.cpp | 57 +++---- 10 files changed, 196 insertions(+), 132 deletions(-) create mode 100644 library/PolyVoxCore/include/PolyVoxCore/Compressor.h diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 41d8ad78..65492a6f 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -49,6 +49,7 @@ SET(CORE_INC_FILES include/PolyVoxCore/BaseVolume.h include/PolyVoxCore/BaseVolume.inl include/PolyVoxCore/BaseVolumeSampler.inl + include/PolyVoxCore/Compressor.h include/PolyVoxCore/ConstVolumeProxy.h include/PolyVoxCore/CubicSurfaceExtractor.h include/PolyVoxCore/CubicSurfaceExtractor.inl diff --git a/library/PolyVoxCore/include/PolyVoxCore/Compressor.h b/library/PolyVoxCore/include/PolyVoxCore/Compressor.h new file mode 100644 index 00000000..2d79d99b --- /dev/null +++ b/library/PolyVoxCore/include/PolyVoxCore/Compressor.h @@ -0,0 +1,42 @@ +/******************************************************************************* +Copyright (c) 2005-2009 David Williams + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*******************************************************************************/ + +#ifndef __PolyVox_Compressor_H__ +#define __PolyVox_Compressor_H__ + +#include "PolyVoxCore/Impl/TypeDef.h" + +namespace PolyVox +{ + class Compressor + { + public: + Compressor() {}; + virtual ~Compressor() {}; + + virtual uint32_t compress(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; + }; +} + +#endif //__PolyVox_Compressor_H__ diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h index 269f0079..ea5541e6 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h @@ -25,6 +25,8 @@ freely, subject to the following restrictions: #define __PolyVox_Block_H__ #include "PolyVoxCore/Impl/TypeDef.h" + +#include "PolyVoxCore/Compressor.h" #include "PolyVoxCore/Vector.h" #include @@ -60,10 +62,9 @@ namespace PolyVox uint32_t calculateSizeInBytes(void); public: - void compress(void); - void uncompress(void); + void compress(Compressor* pCompressor); + void uncompress(Compressor* pCompressor); - std::vector< RunlengthEntry > m_vecCompressedData; void* m_pCompressedData; uint32_t m_uCompressedDataLength; VoxelType* m_tUncompressedData; diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl index 5cdeb34c..3f0829dd 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl @@ -131,20 +131,21 @@ namespace PolyVox m_bIsUncompressedDataModified = true; //For some reason blocks start out compressed. We should probably change this. - compress(); + compress(0); } template uint32_t Block::calculateSizeInBytes(void) { + //FIXME - This function is incomplete. uint32_t uSizeInBytes = sizeof(Block); - uSizeInBytes += m_vecCompressedData.capacity() * sizeof(RunlengthEntry); return uSizeInBytes; } template - void Block::compress(void) + void Block::compress(Compressor* pCompressor) { + //POLYVOX_ASSERT(pCompressor, "Compressor is not valid"); POLYVOX_ASSERT(m_bIsCompressed == false, "Attempted to compress block which is already flagged as compressed."); POLYVOX_ASSERT(m_tUncompressedData != 0, "No uncompressed data is present."); @@ -175,8 +176,9 @@ namespace PolyVox } template - void Block::uncompress(void) + void Block::uncompress(Compressor* pCompressor) { + //POLYVOX_ASSERT(pCompressor, "Compressor is not valid"); POLYVOX_ASSERT(m_bIsCompressed == true, "Attempted to uncompress block which is not flagged as compressed."); POLYVOX_ASSERT(m_tUncompressedData == 0, "Uncompressed data already exists."); diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h index b35f0cae..5cae0359 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h @@ -26,6 +26,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" #include "Impl/Block.h" +#include "PolyVoxCore/Compressor.h" #include "PolyVoxCore/Log.h" #include "PolyVoxCore/Region.h" #include "PolyVoxCore/Vector.h" @@ -256,6 +257,7 @@ namespace PolyVox LargeVolume ( const Region& regValid, + Compressor* pCompressor = 0, polyvox_function&, const Region&)> dataRequiredHandler = 0, polyvox_function&, const Region&)> dataOverflowHandler = 0, bool bPagingEnabled = false, @@ -363,6 +365,9 @@ namespace PolyVox uint16_t m_uBlockSideLength; uint8_t m_uBlockSideLengthPower; + //The compressor used by the Blocks to compress their data if required. + Compressor* m_pCompressor; + bool m_bCompressionEnabled; bool m_bPagingEnabled; }; diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl index 5cc06a9a..a048d03c 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl @@ -62,12 +62,14 @@ namespace PolyVox LargeVolume::LargeVolume ( const Region& regValid, + Compressor* pCompressor, polyvox_function&, const Region&)> dataRequiredHandler, polyvox_function&, const Region&)> dataOverflowHandler, bool bPagingEnabled, uint16_t uBlockSideLength ) :BaseVolume(regValid) + ,m_pCompressor(pCompressor) { m_funcDataRequiredHandler = dataRequiredHandler; m_funcDataOverflowHandler = dataOverflowHandler; @@ -456,7 +458,7 @@ namespace PolyVox { for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) { - m_vecUncompressedBlockCache[ct]->block.compress(); + m_vecUncompressedBlockCache[ct]->block.compress(m_pCompressor); } m_vecUncompressedBlockCache.clear(); } @@ -537,7 +539,7 @@ namespace PolyVox if(m_vecUncompressedBlockCache[ct] == &(itBlock->second)) { // TODO: compression is unneccessary? or will not compressing this cause a memleak? - itBlock->second.block.compress(); + itBlock->second.block.compress(m_pCompressor); // put last object in cache here m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back(); // decrease cache size by one since last element is now in here twice @@ -667,7 +669,7 @@ namespace PolyVox } //Compress the least recently used block. - m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress(); + m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress(m_pCompressor); //We don't actually remove any elements from this vector, we //simply change the pointer to point at the new uncompressed bloack. @@ -678,7 +680,7 @@ namespace PolyVox m_vecUncompressedBlockCache.push_back(&loadedBlock); } - loadedBlock.block.uncompress(); + loadedBlock.block.uncompress(m_pCompressor); m_pLastAccessedBlock = &(loadedBlock.block); POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data"); diff --git a/library/PolyVoxCore/include/PolyVoxCore/MinizCompressor.h b/library/PolyVoxCore/include/PolyVoxCore/MinizCompressor.h index 51474097..3c4ba64d 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MinizCompressor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MinizCompressor.h @@ -1,16 +1,19 @@ #ifndef __PolyVox_MinizCompressor_H__ #define __PolyVox_MinizCompressor_H__ -#include "PolyVoxCore/Impl/TypeDef.h" +#include "PolyVoxCore/Compressor.h" -class MinizCompressor +namespace PolyVox { -public: - MinizCompressor(); - ~MinizCompressor(); + class MinizCompressor : public Compressor + { + public: + MinizCompressor(); + ~MinizCompressor(); - 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 compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); + uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); + }; +} #endif //__PolyVox_MinizCompressor_H__ diff --git a/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.h b/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.h index 8540b5ac..f17cdf51 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.h @@ -1,23 +1,26 @@ #ifndef __PolyVox_RLECompressor_H__ #define __PolyVox_RLECompressor_H__ -#include "PolyVoxCore/Impl/TypeDef.h" +#include "PolyVoxCore/Compressor.h" -template -class RLECompressor +namespace PolyVox { - struct Run + template + class RLECompressor : public Compressor { - ValueType value; - LengthType length; - }; -public: - RLECompressor(); - ~RLECompressor(); + struct Run + { + ValueType value; + LengthType length; + }; + public: + RLECompressor(); + ~RLECompressor(); - 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 compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); + uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength); + }; +} #include "RLECompressor.inl" diff --git a/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.inl b/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.inl index 167206c6..600e2cf9 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/RLECompressor.inl @@ -2,85 +2,87 @@ #include #include -template -RLECompressor::RLECompressor() +namespace PolyVox { -} - -template -RLECompressor::~RLECompressor() -{ -} - -template -uint32_t RLECompressor::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) -{ - assert(uSrcLength % sizeof(ValueType) == 0); - - uSrcLength /= sizeof(ValueType); - uDstLength /= sizeof(Run); - - ValueType* pSrcDataAsInt = reinterpret_cast(pSrcData); - Run* pDstDataAsRun = reinterpret_cast(pDstData); - - ValueType* pSrcDataEnd = pSrcDataAsInt + uSrcLength; - Run* pDstDataEnd = pDstDataAsRun + uDstLength; - - uint32_t uDstLengthInBytes = 0; - - - pDstDataAsRun->value = *pSrcDataAsInt; - pSrcDataAsInt++; - pDstDataAsRun->length = 1; - uDstLengthInBytes += sizeof(Run); - - while(pSrcDataAsInt < pSrcDataEnd) + template + RLECompressor::RLECompressor() { - if((*pSrcDataAsInt == pDstDataAsRun->value) && (pDstDataAsRun->length < (std::numeric_limits::max)())) - { - pDstDataAsRun->length++; - } - else - { - pDstDataAsRun++; - assert(pDstDataAsRun < pDstDataEnd); - pDstDataAsRun->value = *pSrcDataAsInt; - pDstDataAsRun->length = 1; - uDstLengthInBytes += sizeof(Run); - } - + } + + template + RLECompressor::~RLECompressor() + { + } + + template + uint32_t RLECompressor::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) + { + assert(uSrcLength % sizeof(ValueType) == 0); + + uSrcLength /= sizeof(ValueType); + uDstLength /= sizeof(Run); + + ValueType* pSrcDataAsInt = reinterpret_cast(pSrcData); + Run* pDstDataAsRun = reinterpret_cast(pDstData); + + ValueType* pSrcDataEnd = pSrcDataAsInt + uSrcLength; + Run* pDstDataEnd = pDstDataAsRun + uDstLength; + + uint32_t uDstLengthInBytes = 0; + + + pDstDataAsRun->value = *pSrcDataAsInt; pSrcDataAsInt++; + pDstDataAsRun->length = 1; + uDstLengthInBytes += sizeof(Run); + + while(pSrcDataAsInt < pSrcDataEnd) + { + if((*pSrcDataAsInt == pDstDataAsRun->value) && (pDstDataAsRun->length < (std::numeric_limits::max)())) + { + pDstDataAsRun->length++; + } + else + { + pDstDataAsRun++; + assert(pDstDataAsRun < pDstDataEnd); + pDstDataAsRun->value = *pSrcDataAsInt; + pDstDataAsRun->length = 1; + uDstLengthInBytes += sizeof(Run); + } + + pSrcDataAsInt++; + } + + return uDstLengthInBytes; } - return uDstLengthInBytes; -} - -template -uint32_t RLECompressor::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) -{ - assert(uSrcLength % sizeof(Run) == 0); - - uSrcLength /= sizeof(Run); - uDstLength /= sizeof(ValueType); - - Run* pSrcDataAsRun = reinterpret_cast(pSrcData); - ValueType* pDstDataAsInt = reinterpret_cast(pDstData); - - Run* pSrcDataEnd = pSrcDataAsRun + uSrcLength; - ValueType* pDstDataEnd = pDstDataAsInt + uDstLength; - - uint32_t uDstLengthInBytes = 0; - - while(pSrcDataAsRun < pSrcDataEnd) + template + uint32_t RLECompressor::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) { - std::fill(pDstDataAsInt, pDstDataAsInt + pSrcDataAsRun->length, pSrcDataAsRun->value); - pDstDataAsInt += pSrcDataAsRun->length; + assert(uSrcLength % sizeof(Run) == 0); - uDstLengthInBytes += pSrcDataAsRun->length * sizeof(ValueType); - - pSrcDataAsRun++; + uSrcLength /= sizeof(Run); + uDstLength /= sizeof(ValueType); + + Run* pSrcDataAsRun = reinterpret_cast(pSrcData); + ValueType* pDstDataAsInt = reinterpret_cast(pDstData); + + Run* pSrcDataEnd = pSrcDataAsRun + uSrcLength; + ValueType* pDstDataEnd = pDstDataAsInt + uDstLength; + + uint32_t uDstLengthInBytes = 0; + + while(pSrcDataAsRun < pSrcDataEnd) + { + std::fill(pDstDataAsInt, pDstDataAsInt + pSrcDataAsRun->length, pSrcDataAsRun->value); + pDstDataAsInt += pSrcDataAsRun->length; + + uDstLengthInBytes += pSrcDataAsRun->length * sizeof(ValueType); + + pSrcDataAsRun++; + } + + return uDstLengthInBytes; } - - return uDstLengthInBytes; } - diff --git a/library/polyvoxcore/source/MinizCompressor.cpp b/library/polyvoxcore/source/MinizCompressor.cpp index 7e4cbc3e..f0dc06a6 100644 --- a/library/polyvoxcore/source/MinizCompressor.cpp +++ b/library/polyvoxcore/source/MinizCompressor.cpp @@ -14,32 +14,35 @@ // it is then to #include it directly which is what the examples do. #include "PolyVoxCore/Impl/miniz.c" -MinizCompressor::MinizCompressor() +namespace PolyVox { + MinizCompressor::MinizCompressor() + { + } + + MinizCompressor::~MinizCompressor() + { + } + + uint32_t MinizCompressor::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) + { + mz_ulong ulDstLength = uDstLength; + + // Do the compression + int result = mz_compress((unsigned char*)pDstData, &ulDstLength, (const unsigned char*) pSrcData, uSrcLength); + assert(result == MZ_OK); + + // Return the number of bytes written to the output. + return ulDstLength; + } + + uint32_t MinizCompressor::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) + { + mz_ulong ulDstLength = uDstLength; + + int result = mz_uncompress((unsigned char*) pDstData, &ulDstLength, (const unsigned char*) pSrcData, uSrcLength); + assert(result == MZ_OK); + + return ulDstLength; + } } - -MinizCompressor::~MinizCompressor() -{ -} - -uint32_t MinizCompressor::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) -{ - mz_ulong ulDstLength = uDstLength; - - // Do the compression - int result = mz_compress((unsigned char*)pDstData, &ulDstLength, (const unsigned char*) pSrcData, uSrcLength); - assert(result == MZ_OK); - - // Return the number of bytes written to the output. - return ulDstLength; -} - -uint32_t MinizCompressor::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) -{ - mz_ulong ulDstLength = uDstLength; - - int result = mz_uncompress((unsigned char*) pDstData, &ulDstLength, (const unsigned char*) pSrcData, uSrcLength); - assert(result == MZ_OK); - - return ulDstLength; -} \ No newline at end of file