diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 0b0d3de6..f0248c14 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -90,7 +90,7 @@ public: /// Destructor virtual ~PerlinNoisePager() {}; - virtual void pageIn(const PolyVox::Region& region, Chunk* pChunk) + virtual void pageIn(const PolyVox::Region& region, PagedVolume::Chunk* pChunk) { Perlin perlin(2,2,1,234); @@ -134,7 +134,7 @@ public: } } - virtual void pageOut(const PolyVox::Region& region, Chunk* /*pChunk*/) + virtual void pageOut(const PolyVox::Region& region, PagedVolume::Chunk* /*pChunk*/) { std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl; } diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 286f5e14..9704e593 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -38,8 +38,6 @@ SET(CORE_INC_FILES include/PolyVoxCore/BaseVolume.h include/PolyVoxCore/BaseVolume.inl include/PolyVoxCore/BaseVolumeSampler.inl - include/PolyVoxCore/Chunk.h - include/PolyVoxCore/Chunk.inl include/PolyVoxCore/CubicSurfaceExtractor.h include/PolyVoxCore/CubicSurfaceExtractor.inl include/PolyVoxCore/DefaultIsQuadNeeded.h @@ -62,6 +60,7 @@ SET(CORE_INC_FILES include/PolyVoxCore/Mesh.inl include/PolyVoxCore/PagedVolume.h include/PolyVoxCore/PagedVolume.inl + include/PolyVoxCore/PagedVolumeChunk.inl include/PolyVoxCore/PagedVolumeSampler.inl include/PolyVoxCore/Pager.h include/PolyVoxCore/PolyVoxForwardDeclarations.h diff --git a/library/PolyVoxCore/include/PolyVoxCore/Chunk.h b/library/PolyVoxCore/include/PolyVoxCore/Chunk.h deleted file mode 100644 index 1eeec066..00000000 --- a/library/PolyVoxCore/include/PolyVoxCore/Chunk.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2013 David Williams and Matthew Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_Chunk_H__ -#define __PolyVox_Chunk_H__ - -#include "PolyVoxCore/PolyVoxForwardDeclarations.h" -#include "PolyVoxCore/Vector.h" - -namespace PolyVox -{ - template - class Chunk - { - friend class PagedVolume; - - public: - Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager* pPager = nullptr); - ~Chunk(); - - VoxelType* getData(void) const; - uint32_t getDataSizeInBytes(void) const; - - VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const; - VoxelType getVoxel(const Vector3DUint16& v3dPos) const; - - void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); - void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); - - private: - /// Private copy constructor to prevent accisdental copying - Chunk(const Chunk& /*rhs*/) {}; - - /// Private assignment operator to prevent accisdental copying - Chunk& operator=(const Chunk& /*rhs*/) {}; - - // This is updated by the PagedVolume and used to discard the least recently used chunks. - uint32_t m_uChunkLastAccessed; - - // This is so we can tell whether a uncompressed chunk has to be recompressed and whether - // a compressed chunk has to be paged back to disk, or whether they can just be discarded. - bool m_bDataModified; - - uint32_t calculateSizeInBytes(void); - static uint32_t calculateSizeInBytes(uint32_t uSideLength); - - VoxelType* m_tData; - uint16_t m_uSideLength; - uint8_t m_uSideLengthPower; - Pager* m_pPager; - Vector3DInt32 m_v3dChunkSpacePosition; - }; -} - -#include "PolyVoxCore/Chunk.inl" - -#endif diff --git a/library/PolyVoxCore/include/PolyVoxCore/FilePager.h b/library/PolyVoxCore/include/PolyVoxCore/FilePager.h index 26f20c21..269af29c 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/FilePager.h +++ b/library/PolyVoxCore/include/PolyVoxCore/FilePager.h @@ -76,10 +76,10 @@ namespace PolyVox m_vecCreatedFiles.clear(); } - virtual void pageIn(const Region& region, Chunk* pChunk) + virtual void pageIn(const Region& region, typename PagedVolume::Chunk* pChunk) { POLYVOX_ASSERT(pChunk, "Attempting to page in NULL chunk"); - POLYVOX_ASSERT(pChunk->getData() == false, "Chunk must have valid data"); + POLYVOX_ASSERT(pChunk->getData(), "Chunk must have valid data"); std::stringstream ssFilename; ssFilename << m_strFolderName << "/" << m_strRandomPrefix << "-" @@ -120,10 +120,10 @@ namespace PolyVox } } - virtual void pageOut(const Region& region, Chunk* pChunk) + virtual void pageOut(const Region& region, typename PagedVolume::Chunk* pChunk) { POLYVOX_ASSERT(pChunk, "Attempting to page out NULL chunk"); - POLYVOX_ASSERT(pChunk->getData() == false, "Chunk must have valid data"); + POLYVOX_ASSERT(pChunk->getData(), "Chunk must have valid data"); POLYVOX_LOG_TRACE("Paging out data for " << region); diff --git a/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.h b/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.h index 60852007..75acaaca 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.h @@ -27,7 +27,6 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" #include "PolyVoxCore/Pager.h" #include "PolyVoxCore/Region.h" -#include "PolyVoxCore/Chunk.h" #include "PolyVoxCore/Vector.h" #include @@ -157,6 +156,46 @@ namespace PolyVox class PagedVolume : public BaseVolume { public: + + class Chunk + { + public: + Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager* pPager = nullptr); + ~Chunk(); + + VoxelType* getData(void) const; + uint32_t getDataSizeInBytes(void) const; + + VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const; + VoxelType getVoxel(const Vector3DUint16& v3dPos) const; + + void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); + void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); + + public: + /// Private copy constructor to prevent accisdental copying + Chunk(const Chunk& /*rhs*/) {}; + + /// Private assignment operator to prevent accisdental copying + Chunk& operator=(const Chunk& /*rhs*/) {}; + + // This is updated by the PagedVolume and used to discard the least recently used chunks. + uint32_t m_uChunkLastAccessed; + + // This is so we can tell whether a uncompressed chunk has to be recompressed and whether + // a compressed chunk has to be paged back to disk, or whether they can just be discarded. + bool m_bDataModified; + + uint32_t calculateSizeInBytes(void); + static uint32_t calculateSizeInBytes(uint32_t uSideLength); + + VoxelType* m_tData; + uint16_t m_uSideLength; + uint8_t m_uSideLengthPower; + Pager* m_pPager; + Vector3DInt32 m_v3dChunkSpacePosition; + }; + //There seems to be some descrepency between Visual Studio and GCC about how the following class should be declared. //There is a work around (see also See http://goo.gl/qu1wn) given below which appears to work on VS2010 and GCC, but //which seems to cause internal compiler errors on VS2008 when building with the /Gm 'Enable Minimal Rebuild' compiler @@ -285,8 +324,8 @@ namespace PolyVox private: - typedef std::unordered_map > > SharedPtrChunkMap; - typedef std::unordered_map > > WeakPtrChunkMap; + typedef std::unordered_map > SharedPtrChunkMap; + typedef std::unordered_map > WeakPtrChunkMap; void initialise(); @@ -298,7 +337,7 @@ namespace PolyVox VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - std::shared_ptr< Chunk > getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const; + std::shared_ptr getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const; void purgeNullPtrsFromAllChunks(void) const; @@ -308,7 +347,7 @@ namespace PolyVox mutable uint32_t m_uTimestamper; mutable Vector3DInt32 m_v3dLastAccessedChunkPos; - mutable std::shared_ptr< Chunk > m_pLastAccessedChunk; + mutable std::shared_ptr m_pLastAccessedChunk; uint32_t m_uChunkCountLimit; // The size of the volume @@ -328,6 +367,7 @@ namespace PolyVox } #include "PolyVoxCore/PagedVolume.inl" +#include "PolyVoxCore/PagedVolumeChunk.inl" #include "PolyVoxCore/PagedVolumeSampler.inl" #endif //__PolyVox_PagedVolume_H__ diff --git a/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.inl index e307ceb1..ae5aeea3 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/PagedVolume.inl @@ -81,7 +81,7 @@ namespace PolyVox m_uChunkCountLimit = (std::max)(m_uChunkCountLimit, uMinPracticalNoOfChunks); m_uChunkCountLimit = (std::min)(m_uChunkCountLimit, uMaxPracticalNoOfChunks); - uint32_t uChunkSizeInBytes = Chunk::calculateSizeInBytes(m_uChunkSideLength); + uint32_t uChunkSizeInBytes = PagedVolume::Chunk::calculateSizeInBytes(m_uChunkSideLength); POLYVOX_LOG_DEBUG("Memory usage limit for volume initially set to " << (m_uChunkCountLimit * uChunkSizeInBytes) / (1024 * 1024) << "Mb (" << m_uChunkCountLimit << " chunks of " << uChunkSizeInBytes / 1024 << "Kb each)."); @@ -254,7 +254,7 @@ namespace PolyVox POLYVOX_THROW_IF(!m_pPager, invalid_operation, "You cannot limit the memory usage of the volume because it was created without a pager attached."); // Calculate the number of chunks based on the memory limit and the size of each chunk. - uint32_t uChunkSizeInBytes = Chunk::calculateSizeInBytes(m_uChunkSideLength); + uint32_t uChunkSizeInBytes = PagedVolume::Chunk::calculateSizeInBytes(m_uChunkSideLength); m_uChunkCountLimit = uMemoryUsageInBytes / uChunkSizeInBytes; // We need at least a few chunks available to avoid thrashing, and in pratice there will probably be hundreds. @@ -506,7 +506,7 @@ namespace PolyVox } template - std::shared_ptr< Chunk > PagedVolume::getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const + std::shared_ptr::Chunk> PagedVolume::getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const { Vector3DInt32 v3dChunkPos(uChunkX, uChunkY, uChunkZ); @@ -520,7 +520,7 @@ namespace PolyVox } // The chunk was not the same as last time, but we can now hope it is in the set of most recently used chunks. - std::shared_ptr< Chunk > pChunk = nullptr; + std::shared_ptr::Chunk> pChunk = nullptr; typename SharedPtrChunkMap::iterator itChunk = m_pRecentlyUsedChunks.find(v3dChunkPos); // Check whether the chunk was found. @@ -548,7 +548,7 @@ namespace PolyVox else { // The chunk is valid. We know it's not in the recently used list (we checked earlier) so it should be added. - pChunk = std::shared_ptr< Chunk >(itWeakChunk->second); + pChunk = std::shared_ptr< PagedVolume::Chunk >(itWeakChunk->second); m_pRecentlyUsedChunks.insert(std::make_pair(v3dChunkPos, pChunk)); } } @@ -558,7 +558,7 @@ namespace PolyVox if (!pChunk) { // The chunk was not found so we will create a new one. - pChunk = std::make_shared< Chunk >(v3dChunkPos, m_uChunkSideLength, m_pPager); + pChunk = std::make_shared< PagedVolume::Chunk >(v3dChunkPos, m_uChunkSideLength, m_pPager); // As we are loading a new chunk we should try to ensure we don't go over our target memory usage. bool erasedChunk = false; @@ -613,7 +613,7 @@ namespace PolyVox // Note: We disregard the size of the other class members as they are likely to be very small compared to the size of the // allocated voxel data. This also keeps the reported size as a power of two, which makes other memory calculations easier. - return Chunk::calculateSizeInBytes(m_uChunkSideLength) * m_pAllChunks.size(); + return PagedVolume::Chunk::calculateSizeInBytes(m_uChunkSideLength) * m_pAllChunks.size(); } template diff --git a/library/PolyVoxCore/include/PolyVoxCore/Chunk.inl b/library/PolyVoxCore/include/PolyVoxCore/PagedVolumeChunk.inl similarity index 86% rename from library/PolyVoxCore/include/PolyVoxCore/Chunk.inl rename to library/PolyVoxCore/include/PolyVoxCore/PagedVolumeChunk.inl index 49d25aeb..05b713d2 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Chunk.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/PagedVolumeChunk.inl @@ -26,7 +26,7 @@ freely, subject to the following restrictions: namespace PolyVox { template - Chunk::Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager* pPager) + PagedVolume::Chunk::Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager* pPager) :m_uChunkLastAccessed(0) ,m_bDataModified(true) ,m_tData(0) @@ -65,7 +65,7 @@ namespace PolyVox } template - Chunk::~Chunk() + PagedVolume::Chunk::~Chunk() { if (m_pPager && m_bDataModified) { @@ -82,19 +82,19 @@ namespace PolyVox } template - VoxelType* Chunk::getData(void) const + VoxelType* PagedVolume::Chunk::getData(void) const { return m_tData; } template - uint32_t Chunk::getDataSizeInBytes(void) const + uint32_t PagedVolume::Chunk::getDataSizeInBytes(void) const { return m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType); } template - VoxelType Chunk::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const + VoxelType PagedVolume::Chunk::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. @@ -112,13 +112,13 @@ namespace PolyVox } template - VoxelType Chunk::getVoxel(const Vector3DUint16& v3dPos) const + VoxelType PagedVolume::Chunk::getVoxel(const Vector3DUint16& v3dPos) const { return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); } template - void Chunk::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue) + void PagedVolume::Chunk::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. @@ -138,20 +138,20 @@ namespace PolyVox } template - void Chunk::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue) + void PagedVolume::Chunk::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue) { setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } template - uint32_t Chunk::calculateSizeInBytes(void) + uint32_t PagedVolume::Chunk::calculateSizeInBytes(void) { // Call through to the static version return calculateSizeInBytes(m_uSideLength); } template - uint32_t Chunk::calculateSizeInBytes(uint32_t uSideLength) + uint32_t PagedVolume::Chunk::calculateSizeInBytes(uint32_t uSideLength) { // Note: We disregard the size of the other class members as they are likely to be very small compared to the size of the // allocated voxel data. This also keeps the reported size as a power of two, which makes other memory calculations easier. diff --git a/library/PolyVoxCore/include/PolyVoxCore/Pager.h b/library/PolyVoxCore/include/PolyVoxCore/Pager.h index 39d016bb..0280883c 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Pager.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Pager.h @@ -24,7 +24,7 @@ freely, subject to the following restrictions: #ifndef __PolyVox_Pager_H__ #define __PolyVox_Pager_H__ -#include "PolyVoxCore/Chunk.h" +#include "PolyVoxCore/PagedVolume.h" #include "PolyVoxCore/Impl/TypeDef.h" #include @@ -43,8 +43,8 @@ namespace PolyVox /// Destructor virtual ~Pager() {}; - virtual void pageIn(const Region& region, Chunk* pChunk) = 0; - virtual void pageOut(const Region& region, Chunk* pChunk) = 0; + virtual void pageIn(const Region& region, typename PagedVolume::Chunk* pChunk) = 0; + virtual void pageOut(const Region& region, typename PagedVolume::Chunk* pChunk) = 0; }; }