Merge branch 'feature/large-volume-tidying' into develop
This commit is contained in:
commit
acf5bef5e7
@ -21,11 +21,12 @@ freely, subject to the following restrictions:
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "PolyVoxCore/FilePager.h"
|
||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||
#include "PolyVoxCore/LargeVolume.h"
|
||||
#include "PolyVoxCore/LowPassFilter.h"
|
||||
#include "PolyVoxCore/RawVolume.h"
|
||||
#include "PolyVoxCore/RLECompressor.h"
|
||||
#include "PolyVoxCore/RLEBlockCompressor.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
#include "PolyVoxCore/Impl/Utility.h"
|
||||
|
||||
@ -49,8 +50,9 @@ using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
RLECompressor<MaterialDensityPair44, uint16_t>* compressor = new RLECompressor<MaterialDensityPair44, uint16_t>();
|
||||
LargeVolume<MaterialDensityPair44> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(g_uVolumeSideLength-1, g_uVolumeSideLength-1, g_uVolumeSideLength-1)), compressor, 0);
|
||||
RLEBlockCompressor<MaterialDensityPair44>* compressor = new RLEBlockCompressor<MaterialDensityPair44>();
|
||||
FilePager<MaterialDensityPair44>* pager = new FilePager<MaterialDensityPair44>("./");
|
||||
LargeVolume<MaterialDensityPair44> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(g_uVolumeSideLength-1, g_uVolumeSideLength-1, g_uVolumeSideLength-1)), compressor, pager);
|
||||
|
||||
//Make our volume contain a sphere in the center.
|
||||
int32_t minPos = 0;
|
||||
|
@ -28,7 +28,7 @@ freely, subject to the following restrictions:
|
||||
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||
#include "PolyVoxCore/Pager.h"
|
||||
#include "PolyVoxCore/RLECompressor.h"
|
||||
#include "PolyVoxCore/RLEBlockCompressor.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
#include "PolyVoxCore/LargeVolume.h"
|
||||
|
||||
@ -91,9 +91,11 @@ public:
|
||||
/// Destructor
|
||||
virtual ~PerlinNoisePager() {};
|
||||
|
||||
virtual void pageIn(const PolyVox::Region& region, Block<MaterialDensityPair44>* pBlockData)
|
||||
virtual void pageIn(const PolyVox::Region& region, CompressedBlock<MaterialDensityPair44>* pBlockData)
|
||||
{
|
||||
pBlockData->createUncompressedData();
|
||||
// FIXME - this isn't a great example... it's a shame we have to hard clode the block size and also create/destroy
|
||||
// a compressor each time. These could at least be moved outside somewhere if we can't fix it in a better way...
|
||||
UncompressedBlock<MaterialDensityPair44> block(256);
|
||||
|
||||
Perlin perlin(2,2,1,234);
|
||||
|
||||
@ -131,13 +133,18 @@ public:
|
||||
// Voxel position within a block always start from zero. So if a block represents region (4, 8, 12) to (11, 19, 15)
|
||||
// then the valid block voxels are from (0, 0, 0) to (7, 11, 3). Hence we subtract the lower corner position of the
|
||||
// region from the volume space position in order to get the block space position.
|
||||
pBlockData->setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel);
|
||||
block.setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now compress the computed data into the provided block.
|
||||
RLEBlockCompressor<MaterialDensityPair44>* compressor = new RLEBlockCompressor<MaterialDensityPair44>();
|
||||
compressor->compress(&block, pBlockData);
|
||||
delete compressor;
|
||||
}
|
||||
|
||||
virtual void pageOut(const PolyVox::Region& region, Block<MaterialDensityPair44>* /*pBlockData*/)
|
||||
virtual void pageOut(const PolyVox::Region& region, CompressedBlock<MaterialDensityPair44>* /*pBlockData*/)
|
||||
{
|
||||
std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl;
|
||||
}
|
||||
@ -150,12 +157,11 @@ int main(int argc, char *argv[])
|
||||
OpenGLWidget openGLWidget(0);
|
||||
openGLWidget.show();
|
||||
|
||||
RLECompressor<MaterialDensityPair44, uint16_t>* compressor = new RLECompressor<MaterialDensityPair44, uint16_t>();
|
||||
RLEBlockCompressor<MaterialDensityPair44>* compressor = new RLEBlockCompressor<MaterialDensityPair44>();
|
||||
PerlinNoisePager* pager = new PerlinNoisePager();
|
||||
LargeVolume<MaterialDensityPair44> volData(PolyVox::Region::MaxRegion, compressor, pager, 256);
|
||||
//volData.setMaxNumberOfBlocksInMemory(4096);
|
||||
//volData.setMaxNumberOfUncompressedBlocks(64);
|
||||
volData.setTargetMemoryLimitInBytes(128 * 1024 * 1024);
|
||||
volData.setMaxNumberOfBlocksInMemory(4096);
|
||||
volData.setMaxNumberOfUncompressedBlocks(64);
|
||||
|
||||
//volData.setMaxNumberOfUncompressedBlocks(4096);
|
||||
//createSphereInVolume(volData, 30);
|
||||
|
@ -48,6 +48,10 @@ SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/BaseVolume.h
|
||||
include/PolyVoxCore/BaseVolume.inl
|
||||
include/PolyVoxCore/BaseVolumeSampler.inl
|
||||
include/PolyVoxCore/Block.h
|
||||
include/PolyVoxCore/BlockCompressor.h
|
||||
include/PolyVoxCore/CompressedBlock.h
|
||||
include/PolyVoxCore/CompressedBlock.inl
|
||||
include/PolyVoxCore/Compressor.h
|
||||
include/PolyVoxCore/CubicSurfaceExtractor.h
|
||||
include/PolyVoxCore/CubicSurfaceExtractor.inl
|
||||
@ -71,6 +75,8 @@ SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
|
||||
include/PolyVoxCore/Material.h
|
||||
include/PolyVoxCore/MaterialDensityPair.h
|
||||
include/PolyVoxCore/MinizBlockCompressor.h
|
||||
include/PolyVoxCore/MinizBlockCompressor.inl
|
||||
include/PolyVoxCore/MinizCompressor.h
|
||||
include/PolyVoxCore/Pager.h
|
||||
include/PolyVoxCore/PolyVoxForwardDeclarations.h
|
||||
@ -82,14 +88,16 @@ SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/Raycast.h
|
||||
include/PolyVoxCore/Raycast.inl
|
||||
include/PolyVoxCore/Region.h
|
||||
include/PolyVoxCore/RLECompressor.h
|
||||
include/PolyVoxCore/RLECompressor.inl
|
||||
include/PolyVoxCore/RLEBlockCompressor.h
|
||||
include/PolyVoxCore/RLEBlockCompressor.inl
|
||||
include/PolyVoxCore/SimpleVolume.h
|
||||
include/PolyVoxCore/SimpleVolume.inl
|
||||
include/PolyVoxCore/SimpleVolumeBlock.inl
|
||||
include/PolyVoxCore/SimpleVolumeSampler.inl
|
||||
include/PolyVoxCore/SurfaceMesh.h
|
||||
include/PolyVoxCore/SurfaceMesh.inl
|
||||
include/PolyVoxCore/UncompressedBlock.h
|
||||
include/PolyVoxCore/UncompressedBlock.inl
|
||||
include/PolyVoxCore/Vector.h
|
||||
include/PolyVoxCore/Vector.inl
|
||||
include/PolyVoxCore/VertexTypes.h
|
||||
@ -111,8 +119,6 @@ SET(IMPL_INC_FILES
|
||||
include/PolyVoxCore/Impl/ArraySizesImpl.h
|
||||
include/PolyVoxCore/Impl/ArraySizesImpl.inl
|
||||
include/PolyVoxCore/Impl/AStarPathfinderImpl.h
|
||||
include/PolyVoxCore/Impl/Block.h
|
||||
include/PolyVoxCore/Impl/Block.inl
|
||||
include/PolyVoxCore/Impl/CompilerCapabilities.h
|
||||
include/PolyVoxCore/Impl/Config.h
|
||||
include/PolyVoxCore/Impl/ErrorHandling.h
|
||||
|
66
library/PolyVoxCore/include/PolyVoxCore/Block.h
Normal file
66
library/PolyVoxCore/include/PolyVoxCore/Block.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*******************************************************************************
|
||||
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_Block_H__
|
||||
#define __PolyVox_Block_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/PolyVoxForwardDeclarations.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class Block
|
||||
{
|
||||
friend class LargeVolume<VoxelType>;
|
||||
|
||||
public:
|
||||
Block()
|
||||
:m_uBlockLastAccessed(0)
|
||||
,m_bDataModified(true)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
// This is updated by the LargeVolume and used to discard the least recently used blocks.
|
||||
uint32_t m_uBlockLastAccessed;
|
||||
|
||||
// This is so we can tell whether a uncompressed block has to be recompressed and whether
|
||||
// a compressed block has to be paged back to disk, or whether they can just be discarded.
|
||||
bool m_bDataModified;
|
||||
|
||||
private:
|
||||
/// Private copy constructor to prevent accisdental copying
|
||||
Block(const Block& /*rhs*/) {};
|
||||
|
||||
/// Private assignment operator to prevent accisdental copying
|
||||
Block& operator=(const Block& /*rhs*/) {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
48
library/PolyVoxCore/include/PolyVoxCore/BlockCompressor.h
Normal file
48
library/PolyVoxCore/include/PolyVoxCore/BlockCompressor.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
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 compress(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock) = 0;
|
||||
virtual void decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //__PolyVox_BlockCompressor_H__
|
63
library/PolyVoxCore/include/PolyVoxCore/CompressedBlock.h
Normal file
63
library/PolyVoxCore/include/PolyVoxCore/CompressedBlock.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
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
|
79
library/PolyVoxCore/include/PolyVoxCore/CompressedBlock.inl
Normal file
79
library/PolyVoxCore/include/PolyVoxCore/CompressedBlock.inl
Normal file
@ -0,0 +1,79 @@
|
||||
/*******************************************************************************
|
||||
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;
|
||||
}
|
||||
}
|
@ -76,7 +76,7 @@ namespace PolyVox
|
||||
* \param uDstLength The length of the destination buffer (compression will fail if this isn't big enough).
|
||||
* \return The size of the resulting compressed data.
|
||||
*/
|
||||
virtual uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0;
|
||||
virtual uint32_t compress(const void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0;
|
||||
|
||||
/**
|
||||
* Decompresses the data.
|
||||
@ -93,7 +93,7 @@ namespace PolyVox
|
||||
* \param uDstLength The length of the destination buffer (decompression will fail if this isn't big enough).
|
||||
* \return The size of the resulting uncompressed data.
|
||||
*/
|
||||
virtual uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0;
|
||||
virtual uint32_t decompress(const void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@ freely, subject to the following restrictions:
|
||||
#include "PolyVoxCore/Pager.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@ -47,21 +49,39 @@ namespace PolyVox
|
||||
:Pager<VoxelType>()
|
||||
,m_strFolderName(strFolderName)
|
||||
{
|
||||
srand(time(0));
|
||||
int iRandomValue = rand();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::hex << iRandomValue;
|
||||
m_strRandomPrefix = ss.str();
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~FilePager() {};
|
||||
virtual ~FilePager()
|
||||
{
|
||||
for(std::vector<std::string>::iterator iter = m_vecCreatedFiles.begin(); iter < m_vecCreatedFiles.end(); iter++)
|
||||
{
|
||||
if(!std::remove(iter->c_str()))
|
||||
{
|
||||
logWarning() << "Failed to delete '" << *iter << "' when destroying FilePager";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void pageIn(const Region& region, Block<VoxelType>* pBlockData)
|
||||
m_vecCreatedFiles.clear();
|
||||
}
|
||||
|
||||
virtual void pageIn(const Region& region, CompressedBlock<VoxelType>* pBlockData)
|
||||
{
|
||||
POLYVOX_ASSERT(pBlockData, "Attempting to page in NULL block");
|
||||
POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data");
|
||||
//POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data");
|
||||
|
||||
std::stringstream ss;
|
||||
ss << region.getLowerX() << "_" << region.getLowerY() << "_" << region.getLowerZ() << "_"
|
||||
std::stringstream ssFilename;
|
||||
ssFilename << m_strFolderName << "/" << m_strRandomPrefix << "-"
|
||||
<< region.getLowerX() << "_" << region.getLowerY() << "_" << region.getLowerZ() << "_"
|
||||
<< region.getUpperX() << "_" << region.getUpperY() << "_" << region.getUpperZ();
|
||||
|
||||
std::string filename = m_strFolderName + ss.str();
|
||||
std::string filename = ssFilename.str();
|
||||
|
||||
// FIXME - This should be replaced by C++ style IO, but currently this causes problems with
|
||||
// the gameplay-cubiquity integration. See: https://github.com/blackberry/GamePlay/issues/919
|
||||
@ -77,7 +97,7 @@ namespace PolyVox
|
||||
|
||||
uint8_t* buffer = new uint8_t[fileSizeInBytes];
|
||||
fread(buffer, sizeof(uint8_t), fileSizeInBytes, pFile);
|
||||
pBlockData->setCompressedData(buffer, fileSizeInBytes);
|
||||
pBlockData->setData(buffer, fileSizeInBytes);
|
||||
delete[] buffer;
|
||||
|
||||
if(ferror(pFile))
|
||||
@ -93,18 +113,19 @@ namespace PolyVox
|
||||
}
|
||||
}
|
||||
|
||||
virtual void pageOut(const Region& region, Block<VoxelType>* pBlockData)
|
||||
virtual void pageOut(const Region& region, CompressedBlock<VoxelType>* pBlockData)
|
||||
{
|
||||
POLYVOX_ASSERT(pBlockData, "Attempting to page out NULL block");
|
||||
POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data");
|
||||
//POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data");
|
||||
|
||||
logTrace() << "Paging out data for " << region;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << region.getLowerX() << "_" << region.getLowerY() << "_" << region.getLowerZ() << "_"
|
||||
std::stringstream ssFilename;
|
||||
ssFilename << m_strFolderName << "/" << m_strRandomPrefix << "-"
|
||||
<< region.getLowerX() << "_" << region.getLowerY() << "_" << region.getLowerZ() << "_"
|
||||
<< region.getUpperX() << "_" << region.getUpperY() << "_" << region.getUpperZ();
|
||||
|
||||
std::string filename = m_strFolderName + ss.str();
|
||||
std::string filename = ssFilename.str();
|
||||
|
||||
// FIXME - This should be replaced by C++ style IO, but currently this causes problems with
|
||||
// the gameplay-cubiquity integration. See: https://github.com/blackberry/GamePlay/issues/919
|
||||
@ -115,7 +136,10 @@ namespace PolyVox
|
||||
POLYVOX_THROW(std::runtime_error, "Unable to open file to write out block data.");
|
||||
}
|
||||
|
||||
fwrite(pBlockData->getCompressedData(), sizeof(uint8_t), pBlockData->getCompressedDataLength(), pFile);
|
||||
//The file has been created, so add it to the list to delete on shutdown.
|
||||
m_vecCreatedFiles.push_back(filename);
|
||||
|
||||
fwrite(pBlockData->getData(), sizeof(uint8_t), pBlockData->getDataSizeInBytes(), pFile);
|
||||
|
||||
if(ferror(pFile))
|
||||
{
|
||||
@ -127,6 +151,9 @@ namespace PolyVox
|
||||
|
||||
protected:
|
||||
std::string m_strFolderName;
|
||||
std::string m_strRandomPrefix;
|
||||
|
||||
std::vector<std::string> m_vecCreatedFiles;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,277 +0,0 @@
|
||||
/*******************************************************************************
|
||||
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.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "PolyVoxCore/Impl/ErrorHandling.h"
|
||||
#include "PolyVoxCore/Impl/Utility.h"
|
||||
|
||||
#include "PolyVoxCore/Compressor.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include "PolyVoxCore/Impl/ErrorHandling.h"
|
||||
|
||||
#include <cstring> //For memcpy
|
||||
#include <limits>
|
||||
#include <stdexcept> //for std::invalid_argument
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
Block<VoxelType>::Block(uint16_t uSideLength, Compressor* pCompressor)
|
||||
:m_pCompressor(pCompressor)
|
||||
,m_pCompressedData(0)
|
||||
,m_uCompressedDataLength(0)
|
||||
,m_tUncompressedData(0)
|
||||
,m_uSideLength(0)
|
||||
,m_uSideLengthPower(0)
|
||||
,m_bIsUncompressedDataModified(true)
|
||||
{
|
||||
if(uSideLength == 0)
|
||||
{
|
||||
POLYVOX_THROW(std::invalid_argument, "Block side length cannot be zero.");
|
||||
}
|
||||
|
||||
if(!isPowerOf2(uSideLength))
|
||||
{
|
||||
POLYVOX_THROW(std::invalid_argument, "Block side length must be a power of two.");
|
||||
}
|
||||
|
||||
if(pCompressor == 0)
|
||||
{
|
||||
POLYVOX_THROW(std::invalid_argument, "Block must be provided with a valid compressor.");
|
||||
}
|
||||
|
||||
//Compute the side length
|
||||
m_uSideLength = uSideLength;
|
||||
m_uSideLengthPower = logBase2(uSideLength);
|
||||
|
||||
//Temporarily create the block data. This is just so we can compress it an discard it.
|
||||
// FIXME - this is a temporary solution.
|
||||
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
|
||||
m_tUncompressedData = new VoxelType[uNoOfVoxels];
|
||||
std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, VoxelType());
|
||||
m_bIsUncompressedDataModified = true;
|
||||
|
||||
destroyUncompressedData();
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
const uint8_t* Block<VoxelType>::getCompressedData(void) const
|
||||
{
|
||||
POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL");
|
||||
return m_pCompressedData;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t Block<VoxelType>::getCompressedDataLength(void) const
|
||||
{
|
||||
POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL");
|
||||
return m_uCompressedDataLength;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint16_t Block<VoxelType>::getSideLength(void) const
|
||||
{
|
||||
return m_uSideLength;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Block<VoxelType>::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
|
||||
{
|
||||
// This is internal code not directly called by the user. For efficiency we assert rather than throwing.
|
||||
POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(hasUncompressedData(), "The block must have uncompressed data to call getVoxel()");
|
||||
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels.");
|
||||
|
||||
return m_tUncompressedData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
];
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Block<VoxelType>::getVoxel(const Vector3DUint16& v3dPos) const
|
||||
{
|
||||
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
bool Block<VoxelType>::hasUncompressedData(void) const
|
||||
{
|
||||
return m_tUncompressedData != 0;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::setCompressedData(const uint8_t* const data, uint32_t dataLength)
|
||||
{
|
||||
POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL");
|
||||
POLYVOX_ASSERT(m_pCompressedData != data, "Attempting to copy data onto itself");
|
||||
|
||||
delete[] m_pCompressedData;
|
||||
|
||||
m_uCompressedDataLength = dataLength;
|
||||
m_pCompressedData = new uint8_t[dataLength];
|
||||
memcpy(m_pCompressedData, data, dataLength);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
{
|
||||
// This is internal code not directly called by the user. For efficiency we assert rather than throwing.
|
||||
POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(hasUncompressedData(), "The block must have uncompressed data to call setVoxelAt()");
|
||||
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels.");
|
||||
|
||||
m_tUncompressedData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
] = tValue;
|
||||
|
||||
m_bIsUncompressedDataModified = true;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
{
|
||||
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::destroyUncompressedData()
|
||||
{
|
||||
if(!hasUncompressedData())
|
||||
{
|
||||
POLYVOX_THROW(invalid_operation, "No uncompressed data to compress.");
|
||||
}
|
||||
|
||||
POLYVOX_ASSERT(m_tUncompressedData != 0, "No uncompressed data is present.");
|
||||
|
||||
//If the uncompressed data hasn't actually been
|
||||
//modified then we don't need to redo the compression.
|
||||
if(m_bIsUncompressedDataModified)
|
||||
{
|
||||
// Delete the old compressed data as we'll create a new one
|
||||
delete[] m_pCompressedData;
|
||||
m_pCompressedData = 0;
|
||||
|
||||
void* pSrcData = reinterpret_cast<void*>(m_tUncompressedData);
|
||||
uint32_t uSrcLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
|
||||
|
||||
uint8_t tempBuffer[10000];
|
||||
void* pDstData = reinterpret_cast<void*>( tempBuffer );
|
||||
uint32_t uDstLength = 10000;
|
||||
|
||||
uint32_t uCompressedLength = 0;
|
||||
|
||||
try
|
||||
{
|
||||
uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength);
|
||||
|
||||
// Create new compressed data and copy across
|
||||
m_pCompressedData = new uint8_t[uCompressedLength];
|
||||
memcpy(m_pCompressedData, pDstData, uCompressedLength);
|
||||
m_uCompressedDataLength = 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.
|
||||
logWarning() << "The compressor failed to compress the block, proabaly due to the buffer being too small.";
|
||||
logWarning() << "The compression will be tried again with a larger buffer";
|
||||
uint32_t uMaxCompressedSize = m_pCompressor->getMaxCompressedSize(uSrcLength);
|
||||
uint8_t* buffer = new uint8_t[ uMaxCompressedSize ];
|
||||
|
||||
pDstData = reinterpret_cast<void*>( buffer );
|
||||
uDstLength = uMaxCompressedSize;
|
||||
|
||||
try
|
||||
{
|
||||
uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength);
|
||||
|
||||
// Create new compressed data and copy across
|
||||
m_pCompressedData = new uint8_t[uCompressedLength];
|
||||
memcpy(m_pCompressedData, pDstData, uCompressedLength);
|
||||
m_uCompressedDataLength = 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.
|
||||
delete[] buffer;
|
||||
POLYVOX_THROW(std::runtime_error, "Failed to compress block data");
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
//Flag the uncompressed data as no longer being used.
|
||||
delete[] m_tUncompressedData;
|
||||
m_tUncompressedData = 0;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::createUncompressedData()
|
||||
{
|
||||
if(hasUncompressedData())
|
||||
{
|
||||
POLYVOX_THROW(invalid_operation, "Uncompressed data already exists.");
|
||||
}
|
||||
|
||||
POLYVOX_ASSERT(m_tUncompressedData == 0, "Uncompressed data already exists.");
|
||||
|
||||
m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];
|
||||
|
||||
void* pSrcData = reinterpret_cast<void*>(m_pCompressedData);
|
||||
void* pDstData = reinterpret_cast<void*>(m_tUncompressedData);
|
||||
uint32_t uSrcLength = m_uCompressedDataLength;
|
||||
uint32_t uDstLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
|
||||
|
||||
//MinizCompressor compressor;
|
||||
//RLECompressor<VoxelType, uint16_t> compressor;
|
||||
uint32_t uUncompressedLength = m_pCompressor->decompress(pSrcData, uSrcLength, pDstData, uDstLength);
|
||||
|
||||
POLYVOX_ASSERT(uUncompressedLength == m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType), "Destination length has changed.");
|
||||
|
||||
//m_tUncompressedData = reinterpret_cast<VoxelType*>(uncompressedResult.ptr);
|
||||
|
||||
m_bIsUncompressedDataModified = false;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t Block<VoxelType>::calculateSizeInBytes(void)
|
||||
{
|
||||
// Returns the size of this class plus the size of the compressed data. It
|
||||
// doesn't include the uncompressed data cache as that is owned by the volume.
|
||||
uint32_t uSizeInBytes = sizeof(Block<VoxelType>) + m_uCompressedDataLength;
|
||||
return uSizeInBytes;
|
||||
}
|
||||
}
|
@ -25,8 +25,8 @@ freely, subject to the following restrictions:
|
||||
#define __PolyVox_LargeVolume_H__
|
||||
|
||||
#include "PolyVoxCore/BaseVolume.h"
|
||||
#include "Impl/Block.h"
|
||||
#include "PolyVoxCore/Compressor.h"
|
||||
#include "PolyVoxCore/Block.h"
|
||||
#include "PolyVoxCore/BlockCompressor.h"
|
||||
#include "PolyVoxCore/Pager.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
@ -239,7 +239,7 @@ namespace PolyVox
|
||||
LargeVolume
|
||||
(
|
||||
const Region& regValid,
|
||||
Compressor* pCompressor,
|
||||
BlockCompressor<VoxelType>* pBlockCompressor,
|
||||
Pager<VoxelType>* pPager ,
|
||||
uint16_t uBlockSideLength = 32
|
||||
);
|
||||
@ -263,10 +263,10 @@ namespace PolyVox
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
|
||||
void setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes);
|
||||
|
||||
/// Sets the number of blocks for which uncompressed data is stored
|
||||
void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks);
|
||||
/// Sets the number of blocks which can be in memory before the paging system starts unloading them
|
||||
void setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
@ -312,7 +312,10 @@ namespace PolyVox
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
typedef std::map<Vector3DInt32, CompressedBlock<VoxelType>*, BlockPositionCompare> CompressedBlockMap;
|
||||
typedef std::map<Vector3DInt32, UncompressedBlock<VoxelType>*, BlockPositionCompare> UncompressedBlockMap;
|
||||
|
||||
uint32_t calculateBlockMemoryUsage(void) const;
|
||||
|
||||
@ -329,23 +332,21 @@ namespace PolyVox
|
||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const;
|
||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType tBorder) const;
|
||||
|
||||
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||
void eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock) const;
|
||||
CompressedBlock<VoxelType>* getCompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||
UncompressedBlock<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||
|
||||
void eraseBlock(typename CompressedBlockMap::iterator itCompressedBlock) const;
|
||||
void eraseBlock(typename UncompressedBlockMap::iterator itUncompressedBlock) const;
|
||||
|
||||
// The block data
|
||||
mutable std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare> m_pBlocks;
|
||||
mutable CompressedBlockMap m_pBlocks;
|
||||
mutable UncompressedBlockMap m_pUncompressedBlockCache;
|
||||
|
||||
// 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
|
||||
// of blocks. However, this could mean the same block data is uncompressed and modified in more than one
|
||||
// location in memory... could be messy with threading.
|
||||
mutable std::vector< Block<VoxelType>* > m_vecBlocksWithUncompressedData;
|
||||
mutable uint32_t m_uTimestamper;
|
||||
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
||||
mutable Block<VoxelType>* m_pLastAccessedBlock;
|
||||
mutable UncompressedBlock<VoxelType>* m_pLastAccessedBlock;
|
||||
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
||||
|
||||
uint32_t m_uCompressedBlockMemoryLimitInBytes;
|
||||
uint32_t m_uMaxNumberOfBlocksInMemory;
|
||||
|
||||
// The size of the volume
|
||||
Region m_regValidRegionInBlocks;
|
||||
@ -355,9 +356,12 @@ namespace PolyVox
|
||||
uint8_t m_uBlockSideLengthPower;
|
||||
|
||||
// The compressor used by the Blocks to compress their data if required.
|
||||
Compressor* m_pCompressor;
|
||||
BlockCompressor<VoxelType>* m_pBlockCompressor;
|
||||
Pager<VoxelType>* m_pPager;
|
||||
|
||||
// Compressed data for an empty block (sometimes needed for initialisation).
|
||||
//CompressedBlock<VoxelType>* m_pCompressedEmptyBlock;
|
||||
|
||||
// Whether we created the compressor or whether it was provided
|
||||
// by the user. This controls whether we delete it on destruction.
|
||||
bool m_bIsOurCompressor;
|
||||
|
@ -23,7 +23,7 @@ freely, subject to the following restrictions:
|
||||
|
||||
#include "PolyVoxCore/Impl/ErrorHandling.h"
|
||||
|
||||
#include "PolyVoxCore/MinizCompressor.h"
|
||||
#include "PolyVoxCore/MinizBlockCompressor.h" // For creating a default compressor when none is provided.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -45,7 +45,7 @@ namespace PolyVox
|
||||
{
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
|
||||
m_pCompressor = new MinizCompressor();
|
||||
m_pBlockCompressor = new MinizBlockCompressor<VoxelType>();
|
||||
m_bIsOurCompressor = true;
|
||||
|
||||
m_pPager = 0;
|
||||
@ -56,7 +56,7 @@ namespace PolyVox
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This constructor creates a volume with a fixed size which is specified as a parameter. By default this constructor will not enable paging but you can override this if desired. If you do wish to enable paging then you are required to provide the call back function (see the other LargeVolume constructor).
|
||||
/// \param regValid Specifies the minimum and maximum valid voxel positions.
|
||||
/// \param pCompressor An implementation of the Compressor interface which is used to compress blocks in memory.
|
||||
/// \param pBlockCompressor An implementation of the Compressor interface which is used to compress blocks in memory.
|
||||
/// \param dataRequiredHandler The callback function which will be called when PolyVox tries to use data which is not currently in momory.
|
||||
/// \param dataOverflowHandler The callback function which will be called when PolyVox has too much data and needs to remove some from memory.
|
||||
/// \param bPagingEnabled Controls whether or not paging is enabled for this LargeVolume.
|
||||
@ -66,16 +66,15 @@ namespace PolyVox
|
||||
LargeVolume<VoxelType>::LargeVolume
|
||||
(
|
||||
const Region& regValid,
|
||||
Compressor* pCompressor,
|
||||
BlockCompressor<VoxelType>* pBlockCompressor,
|
||||
Pager<VoxelType>* pPager,
|
||||
uint16_t uBlockSideLength
|
||||
)
|
||||
:BaseVolume<VoxelType>(regValid)
|
||||
{
|
||||
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
|
||||
m_pCompressor = pCompressor;
|
||||
m_pBlockCompressor = pBlockCompressor;
|
||||
m_bIsOurCompressor = false;
|
||||
|
||||
m_pPager = pPager;
|
||||
@ -107,8 +106,10 @@ namespace PolyVox
|
||||
// Only delete the compressor if it was created by us (in the constructor), not by the user.
|
||||
if(m_bIsOurCompressor)
|
||||
{
|
||||
delete m_pCompressor;
|
||||
delete m_pBlockCompressor;
|
||||
}
|
||||
|
||||
//delete m_pCompressedEmptyBlock;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -223,9 +224,9 @@ namespace PolyVox
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
const UncompressedBlock<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
return pUncompressedBlock->getVoxel(xOffset,yOffset,zOffset);
|
||||
return pUncompressedBlock->getVoxel(xOffset, yOffset, zOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -243,28 +244,6 @@ namespace PolyVox
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes)
|
||||
{
|
||||
// The size of a single uncompressed block of data.
|
||||
uint32_t uUncompressedBlockSizeInBytes = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
|
||||
// The idea number of uncompressed blocks is chosen by gut feeling as much as anything. Part of the
|
||||
// rationale is that it should let us iterate along any edge without data being pushed out of the cache.
|
||||
uint32_t uIdealNoOfUncompressedBlocks = m_regValidRegionInBlocks.getWidthInVoxels() + m_regValidRegionInBlocks.getHeightInVoxels() * m_regValidRegionInBlocks.getDepthInVoxels();
|
||||
|
||||
// Let's (arbitrarily?) say that we should never use more than half the available memory for the uncompressed block cache.
|
||||
uint32_t uMaxMemoryForUncompressedBlocks = uTargetMemoryLimitInBytes / 2;
|
||||
|
||||
uint32_t uMaxFittableNoOfUncompressedBlocks = uMaxMemoryForUncompressedBlocks / uUncompressedBlockSizeInBytes;
|
||||
|
||||
setMaxNumberOfUncompressedBlocks((std::min)(uIdealNoOfUncompressedBlocks, uMaxFittableNoOfUncompressedBlocks));
|
||||
|
||||
uint32_t uUncompressedBlockCacheSizeInBytes = m_uMaxNumberOfUncompressedBlocks * uUncompressedBlockSizeInBytes;
|
||||
|
||||
m_uCompressedBlockMemoryLimitInBytes = uTargetMemoryLimitInBytes - uUncompressedBlockCacheSizeInBytes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Increasing the size of the block cache will increase memory but may improve performance.
|
||||
/// You may want to set this to a large value (e.g. 1024) when you are first loading your
|
||||
@ -277,6 +256,25 @@ namespace PolyVox
|
||||
clearBlockCache();
|
||||
|
||||
m_uMaxNumberOfUncompressedBlocks = uMaxNumberOfUncompressedBlocks;
|
||||
|
||||
uint32_t uUncompressedBlockSizeInBytes = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
logDebug() << "The maximum number of uncompresed blocks has been set to " << m_uMaxNumberOfUncompressedBlocks
|
||||
<< ", which is " << m_uMaxNumberOfUncompressedBlocks * uUncompressedBlockSizeInBytes << " bytes";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Increasing the number of blocks in memory causes less paging to occur
|
||||
/// \param uMaxNumberOfBlocksInMemory The number of blocks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
flushAll();
|
||||
}
|
||||
|
||||
m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -312,9 +310,8 @@ namespace PolyVox
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
UncompressedBlock<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
pUncompressedBlock->setVoxelAt(xOffset, yOffset, zOffset, tValue);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -350,9 +347,9 @@ namespace PolyVox
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
UncompressedBlock<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;
|
||||
@ -406,7 +403,7 @@ namespace PolyVox
|
||||
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||
{
|
||||
Vector3DInt32 pos(x,y,z);
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos);
|
||||
typename CompressedBlockMap::iterator itBlock = m_pBlocks.find(pos);
|
||||
|
||||
if(itBlock != m_pBlocks.end())
|
||||
{
|
||||
@ -437,7 +434,7 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::flushAll()
|
||||
{
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator i;
|
||||
typename CompressedBlockMap::iterator i;
|
||||
//Replaced the for loop here as the call to
|
||||
//eraseBlock was invalidating the iterator.
|
||||
while(m_pBlocks.size() > 0)
|
||||
@ -471,7 +468,7 @@ namespace PolyVox
|
||||
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||
{
|
||||
Vector3DInt32 pos(x,y,z);
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos);
|
||||
typename CompressedBlockMap::iterator itBlock = m_pBlocks.find(pos);
|
||||
if(itBlock == m_pBlocks.end())
|
||||
{
|
||||
// not loaded, not unloading
|
||||
@ -494,11 +491,6 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::clearBlockCache(void)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++)
|
||||
{
|
||||
m_vecBlocksWithUncompressedData[ct]->destroyUncompressedData();
|
||||
}
|
||||
m_vecBlocksWithUncompressedData.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -518,7 +510,7 @@ namespace PolyVox
|
||||
POLYVOX_THROW(std::invalid_argument, "Block side length must be a power of two.");
|
||||
}
|
||||
|
||||
if(!m_pCompressor)
|
||||
if(!m_pBlockCompressor)
|
||||
{
|
||||
POLYVOX_THROW(std::invalid_argument, "You must provide a valid compressor for the LargeVolume to use.");
|
||||
}
|
||||
@ -554,42 +546,108 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock) const
|
||||
void LargeVolume<VoxelType>::eraseBlock(typename CompressedBlockMap::iterator itCompressedBlock) const
|
||||
{
|
||||
if(itBlock->second.hasUncompressedData())
|
||||
{
|
||||
itBlock->second.destroyUncompressedData();
|
||||
}
|
||||
CompressedBlock<VoxelType>* pCompressedBlock = itCompressedBlock->second;
|
||||
|
||||
if(m_pPager)
|
||||
// Before deleting the block we may need to page out its data. We
|
||||
// only do this if the data has been modified since it was paged in.
|
||||
if(pCompressedBlock->m_bDataModified)
|
||||
{
|
||||
Vector3DInt32 v3dPos = itBlock->first;
|
||||
Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
|
||||
// The position of the block within the volume.
|
||||
Vector3DInt32 v3dBlockPos = itCompressedBlock->first;
|
||||
|
||||
// From the coordinates of the block we deduce the coordinates of the contained voxels.
|
||||
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);
|
||||
// Page the data out
|
||||
m_pPager->pageOut(Region(v3dLower, v3dUpper), pCompressedBlock);
|
||||
|
||||
m_pPager->pageOut(reg, &(itBlock->second));
|
||||
}
|
||||
|
||||
for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++)
|
||||
{
|
||||
// find the block in the uncompressed cache
|
||||
if(m_vecBlocksWithUncompressedData[ct] == &(itBlock->second))
|
||||
{
|
||||
// put last object in cache here
|
||||
m_vecBlocksWithUncompressedData[ct] = m_vecBlocksWithUncompressedData.back();
|
||||
// decrease cache size by one since last element is now in here twice
|
||||
m_vecBlocksWithUncompressedData.resize(m_vecBlocksWithUncompressedData.size()-1);
|
||||
break;
|
||||
}
|
||||
// The compressed data is no longer modified with respect to the data on disk
|
||||
pCompressedBlock->m_bDataModified = false;
|
||||
}
|
||||
|
||||
m_pBlocks.erase(itBlock);
|
||||
delete itCompressedBlock->second;
|
||||
|
||||
// We can now remove the block data from memory.
|
||||
m_pBlocks.erase(itCompressedBlock);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
Block<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
||||
void LargeVolume<VoxelType>::eraseBlock(typename UncompressedBlockMap::iterator itUncompressedBlock) const
|
||||
{
|
||||
UncompressedBlock<VoxelType>* pUncompressedBlock = itUncompressedBlock->second;
|
||||
|
||||
// This should not often happen as blocks are normally deleted based on being least recently used.
|
||||
// However, I can imagine that flushing a large number of blocks could cause this to occur. Just
|
||||
// to be safe we handle it by invalidating the last accessed block pointer.
|
||||
if(pUncompressedBlock == m_pLastAccessedBlock)
|
||||
{
|
||||
logWarning() << "The last accessed block is being erased from the uncompressed cache.";
|
||||
m_pLastAccessedBlock = 0;
|
||||
}
|
||||
|
||||
// Before deleting the block we may need to recompress its data. We
|
||||
// only do this if the data has been modified since it was decompressed.
|
||||
if(pUncompressedBlock->m_bDataModified)
|
||||
{
|
||||
// Get the compressed block which we will copy the data back in to.
|
||||
Vector3DInt32 v3dBlockPos = itUncompressedBlock->first;
|
||||
CompressedBlock<VoxelType>* pCompressedBlock = getCompressedBlock(v3dBlockPos.getX(), v3dBlockPos.getY(), v3dBlockPos.getZ());
|
||||
|
||||
m_pBlockCompressor->compress(pUncompressedBlock, pCompressedBlock);
|
||||
|
||||
// The compressed data has been updated, so the uncompressed data is no longer modified with respect to it.
|
||||
pUncompressedBlock->m_bDataModified = false;
|
||||
}
|
||||
|
||||
delete itUncompressedBlock->second;
|
||||
|
||||
// We can now remove the block data from memory.
|
||||
m_pUncompressedBlockCache.erase(itUncompressedBlock);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
CompressedBlock<VoxelType>* LargeVolume<VoxelType>::getCompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
||||
{
|
||||
Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
|
||||
|
||||
CompressedBlock<VoxelType>* pBlock = 0;
|
||||
|
||||
typename CompressedBlockMap::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
||||
if(itBlock != m_pBlocks.end())
|
||||
{
|
||||
pBlock = itBlock->second;
|
||||
pBlock->m_uBlockLastAccessed = ++m_uTimestamper;
|
||||
return pBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The block wasn't found so we create a new one
|
||||
pBlock = new CompressedBlock<VoxelType>;
|
||||
|
||||
// It's important to set the timestamp before we flush later.
|
||||
pBlock->m_uBlockLastAccessed = ++m_uTimestamper;
|
||||
|
||||
// Pass the block to the Pager to give it a chance to initialise it with any data
|
||||
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);
|
||||
m_pPager->pageIn(reg, pBlock);
|
||||
|
||||
// Add the block to the map
|
||||
itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, pBlock)).first;
|
||||
|
||||
// Paging in this new block may mean we are now using too much memory. If necessary, flush some old blocks.
|
||||
flushOldestExcessiveBlocks();
|
||||
|
||||
return pBlock;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
UncompressedBlock<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
||||
{
|
||||
Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
|
||||
|
||||
@ -599,74 +657,53 @@ namespace PolyVox
|
||||
//This check should also provide a significant speed boost as usually it is true.
|
||||
if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
|
||||
{
|
||||
POLYVOX_ASSERT(m_pLastAccessedBlock->hasUncompressedData(), "Last accessed block has no uncompressed data.");
|
||||
return m_pLastAccessedBlock;
|
||||
}
|
||||
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
||||
// check whether the block is already loaded
|
||||
if(itBlock == m_pBlocks.end())
|
||||
{
|
||||
//The block is not in the map, so we will have to create a new block and add it.
|
||||
Block<VoxelType> newBlock(m_uBlockSideLength, m_pCompressor);
|
||||
itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
|
||||
|
||||
// Now use the pager to fill the block with it's initial data.
|
||||
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);
|
||||
m_pPager->pageIn(reg, &(itBlock->second));
|
||||
|
||||
// Paging in this new block may mean we are now using too much memory. If necessary, flush some old blocks.
|
||||
flushOldestExcessiveBlocks();
|
||||
}
|
||||
|
||||
//Get the block and mark that we accessed it
|
||||
Block<VoxelType>& block = itBlock->second;
|
||||
block.timestamp = ++m_uTimestamper;
|
||||
m_v3dLastAccessedBlockPos = v3dBlockPos;
|
||||
m_pLastAccessedBlock = █
|
||||
|
||||
if(block.hasUncompressedData())
|
||||
{
|
||||
return m_pLastAccessedBlock;
|
||||
}
|
||||
|
||||
//If we are allowed to compress then check whether we need to
|
||||
if(m_vecBlocksWithUncompressedData.size() == m_uMaxNumberOfUncompressedBlocks)
|
||||
typename UncompressedBlockMap::iterator itUncompressedBlock = m_pUncompressedBlockCache.find(v3dBlockPos);
|
||||
// check whether the block is already loaded
|
||||
if(itUncompressedBlock != m_pUncompressedBlockCache.end())
|
||||
{
|
||||
int32_t leastRecentlyUsedBlockIndex = -1;
|
||||
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)();
|
||||
UncompressedBlock<VoxelType>* pUncompressedBlock = itUncompressedBlock->second;
|
||||
|
||||
//Currently we find the oldest block by iterating over the whole array. Of course we could store the blocks sorted by
|
||||
//timestamp (set, priority_queue, etc) but then we'll need to move them around as the timestamp changes. Can come back
|
||||
//to this if it proves to be a bottleneck (compraed to the cost of actually doing the compression/decompression).
|
||||
for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++)
|
||||
{
|
||||
if(m_vecBlocksWithUncompressedData[ct]->timestamp < uLeastRecentTimestamp)
|
||||
{
|
||||
uLeastRecentTimestamp = m_vecBlocksWithUncompressedData[ct]->timestamp;
|
||||
leastRecentlyUsedBlockIndex = ct;
|
||||
}
|
||||
}
|
||||
|
||||
//Compress the least recently used block.
|
||||
m_vecBlocksWithUncompressedData[leastRecentlyUsedBlockIndex]->destroyUncompressedData();
|
||||
pUncompressedBlock->m_uBlockLastAccessed = ++m_uTimestamper;
|
||||
m_pLastAccessedBlock = pUncompressedBlock;
|
||||
m_v3dLastAccessedBlockPos = v3dBlockPos;
|
||||
|
||||
//We don't actually remove any elements from this vector, we
|
||||
//simply change the pointer to point at the new uncompressed bloack.
|
||||
m_vecBlocksWithUncompressedData[leastRecentlyUsedBlockIndex] = █
|
||||
return pUncompressedBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecBlocksWithUncompressedData.push_back(&block);
|
||||
}
|
||||
|
||||
block.createUncompressedData();
|
||||
// At this point we just create a new block.
|
||||
UncompressedBlock<VoxelType>* pUncompressedBlock = new UncompressedBlock<VoxelType>(m_uBlockSideLength);
|
||||
|
||||
// It's important to set the timestamp before we flush later.
|
||||
pUncompressedBlock->m_uBlockLastAccessed = ++m_uTimestamper;
|
||||
|
||||
m_pLastAccessedBlock = &(block);
|
||||
POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data");
|
||||
return m_pLastAccessedBlock;
|
||||
// We set these before flushing because the flush can cause block to be erased, and there
|
||||
// is a test to make sure the block which is being erase is not the last accessed block.
|
||||
m_pLastAccessedBlock = pUncompressedBlock;
|
||||
m_v3dLastAccessedBlockPos = v3dBlockPos;
|
||||
|
||||
// An uncompressed bock is always backed by a compressed one, and this is created by getCompressedBlock() if it doesn't
|
||||
// already exist. If it does already exist and has data then we bring this across into the ucompressed version.
|
||||
if(getCompressedBlock(uBlockX, uBlockY, uBlockZ)->getData() != 0)
|
||||
{
|
||||
// FIXME - multiple getCompressedBlock() calls (including the one above)
|
||||
CompressedBlock<VoxelType>* pBlock = getCompressedBlock(uBlockX, uBlockY, uBlockZ);
|
||||
|
||||
m_pBlockCompressor->decompress(pBlock, pUncompressedBlock);
|
||||
}
|
||||
|
||||
// Add our new block to the map.
|
||||
m_pUncompressedBlockCache.insert(std::make_pair(v3dBlockPos, pUncompressedBlock));
|
||||
|
||||
// Our block cache may now have grown too large. Flush some entries if necessary.
|
||||
// FIXME - Watch out for flushing the block we just created!
|
||||
flushExcessiveCacheEntries();
|
||||
|
||||
return pUncompressedBlock;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -689,16 +726,16 @@ namespace PolyVox
|
||||
uint32_t uSizeInBytes = sizeof(LargeVolume);
|
||||
|
||||
//Memory used by the blocks
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator i;
|
||||
typename CompressedBlockMap::iterator i;
|
||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||
{
|
||||
//Inaccurate - account for rest of loaded block.
|
||||
uSizeInBytes += i->second.calculateSizeInBytes();
|
||||
uSizeInBytes += i->second->calculateSizeInBytes();
|
||||
}
|
||||
|
||||
//Memory used by the block cache.
|
||||
uSizeInBytes += m_vecBlocksWithUncompressedData.capacity() * sizeof(Block<VoxelType>);
|
||||
uSizeInBytes += m_vecBlocksWithUncompressedData.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
//uSizeInBytes += m_vecBlocksWithUncompressedData.capacity() * sizeof(Block<VoxelType>);
|
||||
//uSizeInBytes += m_vecBlocksWithUncompressedData.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
|
||||
return uSizeInBytes;
|
||||
}
|
||||
@ -708,11 +745,11 @@ namespace PolyVox
|
||||
{
|
||||
uint32_t uMemoryUsage = 0;
|
||||
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator i;
|
||||
typename CompressedBlockMap::iterator i;
|
||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||
{
|
||||
//Inaccurate - account for rest of loaded block.
|
||||
uMemoryUsage += i->second.calculateSizeInBytes();
|
||||
uMemoryUsage += i->second->calculateSizeInBytes();
|
||||
}
|
||||
|
||||
return uMemoryUsage;
|
||||
@ -721,27 +758,21 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::flushOldestExcessiveBlocks(void) const
|
||||
{
|
||||
const uint32_t uMemoryUsedForCompressedBlocks = calculateBlockMemoryUsage();
|
||||
uint32_t uMemoryToReclaim = uMemoryUsedForCompressedBlocks - m_uCompressedBlockMemoryLimitInBytes;
|
||||
|
||||
//while(uMemoryToReclaim > 0)
|
||||
while(calculateBlockMemoryUsage() > m_uCompressedBlockMemoryLimitInBytes) //FIXME - This calculation of size is slow and should be outside the loop.
|
||||
while(m_pBlocks.size() > m_uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
// find the least recently used block
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator i;
|
||||
typename std::map<Vector3DInt32, Block<VoxelType>, BlockPositionCompare>::iterator itUnloadBlock = m_pBlocks.begin();
|
||||
// Find the least recently used block. This is somewhat inefficient as it searches through
|
||||
// the map, so if it proves to be a bottleneck we may want some kind of sorted structure.
|
||||
typename CompressedBlockMap::iterator i;
|
||||
typename CompressedBlockMap::iterator itUnloadBlock = m_pBlocks.begin();
|
||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||
{
|
||||
if(i->second.timestamp < itUnloadBlock->second.timestamp)
|
||||
if(i->second->m_uBlockLastAccessed < itUnloadBlock->second->m_uBlockLastAccessed)
|
||||
{
|
||||
itUnloadBlock = i;
|
||||
}
|
||||
}
|
||||
|
||||
POLYVOX_ASSERT(itUnloadBlock->second.hasUncompressedData() == false, "This function should never flush blocks with uncompressed data.");
|
||||
|
||||
uMemoryToReclaim -= itUnloadBlock->second.calculateSizeInBytes();
|
||||
|
||||
// Erase the least recently used block
|
||||
eraseBlock(itUnloadBlock);
|
||||
}
|
||||
}
|
||||
@ -749,6 +780,23 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::flushExcessiveCacheEntries(void) const
|
||||
{
|
||||
while(m_pUncompressedBlockCache.size() > m_uMaxNumberOfUncompressedBlocks)
|
||||
{
|
||||
// Find the least recently used block. The uncompressed block cache should be
|
||||
// much smaller than the total number of blocks, so hopefully this isn't too slow.
|
||||
typename UncompressedBlockMap::iterator i;
|
||||
typename UncompressedBlockMap::iterator itUnloadBlock = m_pUncompressedBlockCache.begin();
|
||||
for(i = m_pUncompressedBlockCache.begin(); i != m_pUncompressedBlockCache.end(); i++)
|
||||
{
|
||||
if(i->second->m_uBlockLastAccessed < itUnloadBlock->second->m_uBlockLastAccessed)
|
||||
{
|
||||
itUnloadBlock = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Erase the least recently used block
|
||||
eraseBlock(itUnloadBlock);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
@ -808,9 +856,8 @@ namespace PolyVox
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
return pUncompressedBlock->getVoxel(xOffset,yOffset,zOffset);
|
||||
UncompressedBlock<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
return pUncompressedBlock->getVoxel(xOffset, yOffset, zOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,9 +119,9 @@ namespace PolyVox
|
||||
uYPosInBlock * this->mVolume->m_uBlockSideLength +
|
||||
uZPosInBlock * this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
|
||||
Block<VoxelType>* pUncompressedCurrentBlock = this->mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock);
|
||||
UncompressedBlock<VoxelType>* pUncompressedCurrentBlock = this->mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock);
|
||||
|
||||
mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock;
|
||||
mCurrentVoxel = pUncompressedCurrentBlock->m_tData + uVoxelIndexInBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*******************************************************************************
|
||||
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/MinizCompressor.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
* Provides an interface for performing paging of data.
|
||||
*/
|
||||
template <typename VoxelType>
|
||||
class MinizBlockCompressor : public BlockCompressor<VoxelType>
|
||||
{
|
||||
public:
|
||||
MinizBlockCompressor();
|
||||
~MinizBlockCompressor();
|
||||
|
||||
void compress(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock);
|
||||
void decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock);
|
||||
|
||||
MinizCompressor* m_pCompressor;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/MinizBlockCompressor.inl"
|
||||
|
||||
#endif //__PolyVox_MinizBlockCompressor_H__
|
105
library/PolyVoxCore/include/PolyVoxCore/MinizBlockCompressor.inl
Normal file
105
library/PolyVoxCore/include/PolyVoxCore/MinizBlockCompressor.inl
Normal file
@ -0,0 +1,105 @@
|
||||
/*******************************************************************************
|
||||
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>
|
||||
MinizBlockCompressor<VoxelType>::MinizBlockCompressor()
|
||||
{
|
||||
m_pCompressor = new MinizCompressor;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
MinizBlockCompressor<VoxelType>::~MinizBlockCompressor()
|
||||
{
|
||||
delete m_pCompressor;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void MinizBlockCompressor<VoxelType>::compress(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock)
|
||||
{
|
||||
void* pSrcData = reinterpret_cast<void*>(pSrcBlock->getData());
|
||||
uint32_t uSrcLength = pSrcBlock->getDataSizeInBytes();
|
||||
|
||||
uint8_t tempBuffer[10000];
|
||||
uint8_t* pDstData = reinterpret_cast<uint8_t*>( tempBuffer );
|
||||
uint32_t uDstLength = 10000;
|
||||
|
||||
uint32_t uCompressedLength = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// Perform the compression
|
||||
uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength);
|
||||
|
||||
// Copy the resulting compressed data into the compressed block
|
||||
pDstBlock->setData(pDstData, uDstLength);
|
||||
}
|
||||
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.
|
||||
logWarning() << "The compressor failed to compress the block, probabaly due to the buffer being too small.";
|
||||
logWarning() << "The compression will be tried again with a larger buffer";
|
||||
uint32_t uMaxCompressedSize = m_pCompressor->getMaxCompressedSize(uSrcLength);
|
||||
uint8_t* buffer = new uint8_t[ uMaxCompressedSize ];
|
||||
|
||||
pDstData = reinterpret_cast<uint8_t*>( buffer );
|
||||
uDstLength = uMaxCompressedSize;
|
||||
|
||||
try
|
||||
{
|
||||
// Perform the compression
|
||||
uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength);
|
||||
|
||||
// Copy the resulting compressed data into the compressed block
|
||||
pDstBlock->setData(pDstData, uDstLength);
|
||||
}
|
||||
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.
|
||||
delete[] buffer;
|
||||
POLYVOX_THROW(std::runtime_error, "Failed to compress block data");
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void MinizBlockCompressor<VoxelType>::decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock)
|
||||
{
|
||||
const void* pSrcData = reinterpret_cast<const void*>(pSrcBlock->getData());
|
||||
void* pDstData = reinterpret_cast<void*>(pDstBlock->getData());
|
||||
uint32_t uSrcLength = pSrcBlock->getDataSizeInBytes();
|
||||
uint32_t uDstLength = pDstBlock->getDataSizeInBytes();
|
||||
|
||||
|
||||
//RLECompressor<VoxelType, uint16_t> compressor;
|
||||
uint32_t uUncompressedLength = m_pCompressor->decompress(pSrcData, uSrcLength, pDstData, uDstLength);
|
||||
|
||||
POLYVOX_ASSERT(uUncompressedLength == pDstBlock->getDataSizeInBytes(), "Destination length has changed.");
|
||||
}
|
||||
}
|
@ -25,8 +25,8 @@ namespace PolyVox
|
||||
|
||||
// API documentation is in base class and gets inherited by Doxygen.
|
||||
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);
|
||||
uint32_t compress(const void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength);
|
||||
uint32_t decompress(const void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength);
|
||||
|
||||
private:
|
||||
unsigned int m_uCompressionFlags;
|
||||
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
||||
#ifndef __PolyVox_Pager_H__
|
||||
#define __PolyVox_Pager_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/Block.h"
|
||||
#include "PolyVoxCore/CompressedBlock.h"
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
@ -41,8 +41,8 @@ namespace PolyVox
|
||||
/// Destructor
|
||||
virtual ~Pager() {};
|
||||
|
||||
virtual void pageIn(const Region& region, Block<VoxelType>* pBlockData) = 0;
|
||||
virtual void pageOut(const Region& region, Block<VoxelType>* pBlockData) = 0;
|
||||
virtual void pageIn(const Region& region, CompressedBlock<VoxelType>* pBlockData) = 0;
|
||||
virtual void pageOut(const Region& region, CompressedBlock<VoxelType>* pBlockData) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,11 @@ namespace PolyVox
|
||||
typedef Array<3,int32_t> Array3DInt32;
|
||||
typedef Array<3,uint32_t> Array3DUint32;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BlockCompressor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType> class BlockCompressor;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Compressor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
61
library/PolyVoxCore/include/PolyVoxCore/RLEBlockCompressor.h
Normal file
61
library/PolyVoxCore/include/PolyVoxCore/RLEBlockCompressor.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
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"
|
||||
|
||||
#include "PolyVoxCore/MinizCompressor.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 compress(UncompressedBlock<VoxelType>* pSrcBlock, CompressedBlock<VoxelType>* pDstBlock);
|
||||
void decompress(CompressedBlock<VoxelType>* pSrcBlock, UncompressedBlock<VoxelType>* pDstBlock);
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/RLEBlockCompressor.inl"
|
||||
|
||||
#endif //__PolyVox_RLEBlockCompressor_H__
|
167
library/PolyVoxCore/include/PolyVoxCore/RLEBlockCompressor.inl
Normal file
167
library/PolyVoxCore/include/PolyVoxCore/RLEBlockCompressor.inl
Normal file
@ -0,0 +1,167 @@
|
||||
/*******************************************************************************
|
||||
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>::compress(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.");
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#ifndef __PolyVox_RLECompressor_H__
|
||||
#define __PolyVox_RLECompressor_H__
|
||||
|
||||
#include "PolyVoxCore/Compressor.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
* Performs compression of data using Run Length Encoding (RLE).
|
||||
*
|
||||
* This compressor is designed for voxel data which contains long runs of the same value. Minecraft-style terrain and other
|
||||
* cubic-style terrains are likely to fall under this category, whereas density fields for Marching Cubes terrain will not. Please
|
||||
* see the following article if you want more details of how RLE compression works: http://en.wikipedia.org/wiki/Run-length_encoding
|
||||
*
|
||||
* \sa MinizCompressor
|
||||
*/
|
||||
template<typename ValueType, typename LengthType>
|
||||
class RLECompressor : public Compressor
|
||||
{
|
||||
struct Run
|
||||
{
|
||||
ValueType value;
|
||||
LengthType length;
|
||||
};
|
||||
public:
|
||||
/// Constructor
|
||||
RLECompressor();
|
||||
/// Destructor
|
||||
~RLECompressor();
|
||||
|
||||
// API documentation is in base class and gets inherited by Doxygen.
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
#include "RLECompressor.inl"
|
||||
|
||||
#endif //__PolyVox_RLECompressor_H__
|
@ -1,126 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename ValueType, typename LengthType>
|
||||
RLECompressor<ValueType, LengthType>::RLECompressor()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ValueType, typename LengthType>
|
||||
RLECompressor<ValueType, LengthType>::~RLECompressor()
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if(uSrcLength % sizeof(ValueType) != 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(ValueType);
|
||||
uDstLength /= sizeof(Run);
|
||||
|
||||
// Get data pointers in the appropriate type
|
||||
ValueType* pSrcDataAsType = reinterpret_cast<ValueType*>(pSrcData);
|
||||
Run* pDstDataAsRun = reinterpret_cast<Run*>(pDstData);
|
||||
|
||||
// Pointers to just past the end of the data
|
||||
ValueType* 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);
|
||||
|
||||
//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.
|
||||
if((*pSrcDataAsType == pDstDataAsRun->value) && (pDstDataAsRun->length < (std::numeric_limits<LengthType>::max)()))
|
||||
{
|
||||
pDstDataAsRun->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);
|
||||
}
|
||||
|
||||
pSrcDataAsType++;
|
||||
}
|
||||
|
||||
return uDstLengthInBytes;
|
||||
}
|
||||
|
||||
template<typename ValueType, typename LengthType>
|
||||
uint32_t RLECompressor<ValueType, LengthType>::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
|
||||
{
|
||||
if(uSrcLength % sizeof(Run) != 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);
|
||||
uDstLength /= sizeof(ValueType);
|
||||
|
||||
// Get data pointers in the appropriate type
|
||||
Run* pSrcDataAsRun = reinterpret_cast<Run*>(pSrcData);
|
||||
ValueType* pDstDataAsType = reinterpret_cast<ValueType*>(pDstData);
|
||||
|
||||
// Pointers to just past the end of the data
|
||||
Run* pSrcDataEnd = pSrcDataAsRun + uSrcLength;
|
||||
ValueType* 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.");
|
||||
}
|
||||
|
||||
// Write the run into the destination
|
||||
std::fill(pDstDataAsType, pDstDataAsType + pSrcDataAsRun->length, pSrcDataAsRun->value);
|
||||
pDstDataAsType += pSrcDataAsRun->length;
|
||||
|
||||
uDstLengthInBytes += pSrcDataAsRun->length * sizeof(ValueType);
|
||||
pSrcDataAsRun++;
|
||||
}
|
||||
|
||||
return uDstLengthInBytes;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
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
|
||||
@ -21,55 +21,48 @@ freely, subject to the following restrictions:
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __PolyVox_Block_H__
|
||||
#define __PolyVox_Block_H__
|
||||
#ifndef __PolyVox_UncompressedBlock_H__
|
||||
#define __PolyVox_UncompressedBlock_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/PolyVoxForwardDeclarations.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include "PolyVoxCore/Block.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
Block(uint16_t uSideLength, Compressor* pCompressor);
|
||||
class UncompressedBlock : public Block<VoxelType>
|
||||
{
|
||||
friend class LargeVolume<VoxelType>;
|
||||
|
||||
public:
|
||||
UncompressedBlock(uint16_t uSideLength);
|
||||
~UncompressedBlock();
|
||||
|
||||
VoxelType* getData(void) const;
|
||||
uint32_t getDataSizeInBytes(void) const;
|
||||
|
||||
const uint8_t* getCompressedData(void) const;
|
||||
uint32_t getCompressedDataLength(void) const;
|
||||
uint16_t getSideLength(void) const;
|
||||
VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||
VoxelType getVoxel(const Vector3DUint16& v3dPos) const;
|
||||
|
||||
bool hasUncompressedData(void) const;
|
||||
|
||||
void setCompressedData(const uint8_t* const data, uint32_t dataLength);
|
||||
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||
|
||||
void createUncompressedData(void);
|
||||
void destroyUncompressedData(void);
|
||||
private:
|
||||
/// Private copy constructor to prevent accisdental copying
|
||||
UncompressedBlock(const UncompressedBlock& /*rhs*/) {};
|
||||
|
||||
/// Private assignment operator to prevent accisdental copying
|
||||
UncompressedBlock& operator=(const UncompressedBlock& /*rhs*/) {};
|
||||
|
||||
// Made this private for consistancy with CompressedBlock.
|
||||
// Users shouldn't really need this for UncompressedBlock anyway.
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
|
||||
public:
|
||||
Compressor* m_pCompressor;
|
||||
uint8_t* m_pCompressedData;
|
||||
uint32_t m_uCompressedDataLength;
|
||||
VoxelType* m_tUncompressedData;
|
||||
uint16_t m_uSideLength;
|
||||
uint8_t m_uSideLengthPower;
|
||||
bool m_bIsUncompressedDataModified;
|
||||
|
||||
uint32_t timestamp;
|
||||
VoxelType* m_tData;
|
||||
uint16_t m_uSideLength;
|
||||
uint8_t m_uSideLengthPower;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/Impl/Block.inl"
|
||||
#include "PolyVoxCore/UncompressedBlock.inl"
|
||||
|
||||
#endif
|
117
library/PolyVoxCore/include/PolyVoxCore/UncompressedBlock.inl
Normal file
117
library/PolyVoxCore/include/PolyVoxCore/UncompressedBlock.inl
Normal file
@ -0,0 +1,117 @@
|
||||
/*******************************************************************************
|
||||
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>
|
||||
UncompressedBlock<VoxelType>::UncompressedBlock(uint16_t uSideLength)
|
||||
:m_tData(0)
|
||||
,m_uSideLength(0)
|
||||
,m_uSideLengthPower(0)
|
||||
{
|
||||
// Compute the side length
|
||||
m_uSideLength = uSideLength;
|
||||
m_uSideLengthPower = logBase2(uSideLength);
|
||||
|
||||
// Allocate the data
|
||||
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
|
||||
m_tData = new VoxelType[uNoOfVoxels];
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
UncompressedBlock<VoxelType>::~UncompressedBlock()
|
||||
{
|
||||
delete[] m_tData;
|
||||
m_tData = 0;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType* UncompressedBlock<VoxelType>::getData(void) const
|
||||
{
|
||||
return m_tData;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t UncompressedBlock<VoxelType>::getDataSizeInBytes(void) const
|
||||
{
|
||||
return m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType UncompressedBlock<VoxelType>::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
|
||||
{
|
||||
// This code is not usually expected to be called by the user, with the exception of when implementing paging
|
||||
// of uncompressed data. It's a performance critical code path so we use asserts rather than exceptions.
|
||||
POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(m_tData, "No uncompressed data - block must be decompressed before accessing voxels.");
|
||||
|
||||
return m_tData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
];
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType UncompressedBlock<VoxelType>::getVoxel(const Vector3DUint16& v3dPos) const
|
||||
{
|
||||
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void UncompressedBlock<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
{
|
||||
// This code is not usually expected to be called by the user, with the exception of when implementing paging
|
||||
// of uncompressed data. It's a performance critical code path so we use asserts rather than exceptions.
|
||||
POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block");
|
||||
POLYVOX_ASSERT(m_tData, "No uncompressed data - block must be decompressed before accessing voxels.");
|
||||
|
||||
m_tData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
] = tValue;
|
||||
|
||||
this->m_bDataModified = true;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void UncompressedBlock<VoxelType>::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
{
|
||||
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t UncompressedBlock<VoxelType>::calculateSizeInBytes(void)
|
||||
{
|
||||
// Returns the size of this class plus the size of the uncompressed data.
|
||||
uint32_t uSizeInBytes = sizeof(UncompressedBlock<VoxelType>) + (m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType));
|
||||
return uSizeInBytes;
|
||||
}
|
||||
}
|
@ -70,7 +70,7 @@ namespace PolyVox
|
||||
return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
|
||||
}
|
||||
|
||||
uint32_t MinizCompressor::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
|
||||
uint32_t MinizCompressor::compress(const void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
|
||||
{
|
||||
//Get the deflator
|
||||
tdefl_compressor* pDeflator = reinterpret_cast<tdefl_compressor*>(m_pDeflator);
|
||||
@ -103,7 +103,7 @@ namespace PolyVox
|
||||
return ulDstLength;
|
||||
}
|
||||
|
||||
uint32_t MinizCompressor::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
|
||||
uint32_t MinizCompressor::decompress(const void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_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 detination is a Block and those are always a power of two. If you need to use this class for other purposes then you'll
|
||||
|
9
library/bindings/Block.i
Normal file
9
library/bindings/Block.i
Normal file
@ -0,0 +1,9 @@
|
||||
%module Block
|
||||
%{
|
||||
#include "Block.h"
|
||||
%}
|
||||
|
||||
%include "Block.h"
|
||||
|
||||
VOLUMETYPES(Block)
|
||||
|
8
library/bindings/BlockCompressor.i
Normal file
8
library/bindings/BlockCompressor.i
Normal file
@ -0,0 +1,8 @@
|
||||
%module BlockCompressor
|
||||
%{
|
||||
#include "BlockCompressor.h"
|
||||
%}
|
||||
|
||||
%include "BlockCompressor.h"
|
||||
|
||||
VOLUMETYPES(BlockCompressor)
|
8
library/bindings/CompressedBlock.i
Normal file
8
library/bindings/CompressedBlock.i
Normal file
@ -0,0 +1,8 @@
|
||||
%module CompressedBlock
|
||||
%{
|
||||
#include "CompressedBlock.h"
|
||||
%}
|
||||
|
||||
%include "CompressedBlock.h"
|
||||
|
||||
VOLUMETYPES(CompressedBlock)
|
6
library/bindings/MinizBlockCompressor.i
Normal file
6
library/bindings/MinizBlockCompressor.i
Normal file
@ -0,0 +1,6 @@
|
||||
%module MinizBlockCompressor
|
||||
%{
|
||||
#include "MinizBlockCompressor.h"
|
||||
%}
|
||||
|
||||
%include "MinizBlockCompressor.h"
|
@ -1,6 +0,0 @@
|
||||
%module MinizCompressor
|
||||
%{
|
||||
#include "MinizCompressor.h"
|
||||
%}
|
||||
|
||||
%include "MinizCompressor.h"
|
@ -76,11 +76,15 @@ EXTRACTOR(shortname, LargeVolume)
|
||||
%include "Vector.i"
|
||||
%include "DefaultMarchingCubesController.i"
|
||||
%include "Region.i"
|
||||
%include "Block.i"
|
||||
%include "CompressedBlock.i"
|
||||
%include "UncompressedBlock.i"
|
||||
%include "Compressor.i"
|
||||
%include "BlockCompressor.i"
|
||||
%include "Pager.i"
|
||||
%include "FilePager.i"
|
||||
%include "MinizCompressor.i"
|
||||
%include "RLECompressor.i"
|
||||
%include "MinizBlockCompressor.i"
|
||||
%include "RLEBlockCompressor.i"
|
||||
%include "BaseVolume.i"
|
||||
%include "SimpleVolume.i"
|
||||
%include "RawVolume.i"
|
||||
|
6
library/bindings/RLEBlockCompressor.i
Normal file
6
library/bindings/RLEBlockCompressor.i
Normal file
@ -0,0 +1,6 @@
|
||||
%module RLEBlockCompressor
|
||||
%{
|
||||
#include "RLEBlockCompressor.h"
|
||||
%}
|
||||
|
||||
%include "RLEBlockCompressor.h"
|
@ -1,6 +0,0 @@
|
||||
%module RLECompressor
|
||||
%{
|
||||
#include "RLECompressor.h"
|
||||
%}
|
||||
|
||||
%include "RLECompressor.h"
|
8
library/bindings/UncompressedBlock.i
Normal file
8
library/bindings/UncompressedBlock.i
Normal file
@ -0,0 +1,8 @@
|
||||
%module UncompressedBlock
|
||||
%{
|
||||
#include "UncompressedBlock.h"
|
||||
%}
|
||||
|
||||
%include "UncompressedBlock.h"
|
||||
|
||||
VOLUMETYPES(UncompressedBlock)
|
@ -25,9 +25,8 @@ freely, subject to the following restrictions:
|
||||
|
||||
#include "PolyVoxCore/FilePager.h"
|
||||
#include "PolyVoxCore/LargeVolume.h"
|
||||
#include "PolyVoxCore/MinizCompressor.h"
|
||||
#include "PolyVoxCore/MinizBlockCompressor.h"
|
||||
#include "PolyVoxCore/RawVolume.h"
|
||||
#include "PolyVoxCore/RLECompressor.h"
|
||||
#include "PolyVoxCore/SimpleVolume.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
@ -273,17 +272,16 @@ TestVolume::TestVolume()
|
||||
Region region(-57, -31, 12, 64, 96, 131); // Deliberatly awkward size
|
||||
|
||||
//m_pCompressor = new RLECompressor<int32_t, uint16_t>;
|
||||
m_pCompressor = new MinizCompressor;
|
||||
m_pBlockCompressor = new MinizBlockCompressor<int32_t>;
|
||||
m_pFilePager = new FilePager<int32_t>("./");
|
||||
|
||||
//Create the volumes
|
||||
m_pRawVolume = new RawVolume<int32_t>(region);
|
||||
m_pSimpleVolume = new SimpleVolume<int32_t>(region);
|
||||
m_pLargeVolume = new LargeVolume<int32_t>(region, m_pCompressor, m_pFilePager, 32);
|
||||
m_pLargeVolume = new LargeVolume<int32_t>(region, m_pBlockCompressor, m_pFilePager, 32);
|
||||
|
||||
//m_pLargeVolume->setMaxNumberOfBlocksInMemory(32);
|
||||
//m_pLargeVolume->setMaxNumberOfUncompressedBlocks(16);
|
||||
m_pLargeVolume->setTargetMemoryLimitInBytes(4 * 1024 * 1024);
|
||||
m_pLargeVolume->setMaxNumberOfBlocksInMemory(32);
|
||||
m_pLargeVolume->setMaxNumberOfUncompressedBlocks(16);
|
||||
|
||||
//Fill the volume with some data
|
||||
for(int z = region.getLowerZ(); z <= region.getUpperZ(); z++)
|
||||
@ -308,7 +306,7 @@ TestVolume::~TestVolume()
|
||||
delete m_pLargeVolume;
|
||||
|
||||
delete m_pFilePager;
|
||||
delete m_pCompressor;
|
||||
delete m_pBlockCompressor;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -65,7 +65,7 @@ private slots:
|
||||
void testLargeVolumeSamplersWithExternalBackwards();
|
||||
|
||||
private:
|
||||
PolyVox::Compressor* m_pCompressor;
|
||||
PolyVox::BlockCompressor<int32_t>* m_pBlockCompressor;
|
||||
PolyVox::FilePager<int32_t>* m_pFilePager;
|
||||
|
||||
PolyVox::RawVolume<int32_t>* m_pRawVolume;
|
||||
|
Loading…
x
Reference in New Issue
Block a user