diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 4d359082..c73b8f5b 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -422,6 +422,39 @@ void createPerlinVolumeFast(Volume& volData) } } +void createPerlinTerrain(Volume& volData) +{ + Perlin perlin(2,2,1,234); + + for(int x = 1; x < volData.getWidth()-1; x++) + { + std::cout << x << std::endl; + for(int y = 1; y < volData.getHeight()-1; y++) + { + float perlinVal = perlin.Get(x / static_cast(volData.getHeight()-1), y / static_cast(volData.getDepth()-1)); + perlinVal += 1.0f; + perlinVal *= 0.5f; + perlinVal *= volData.getWidth(); + for(int z = 1; z < volData.getDepth()-1; z++) + { + MaterialDensityPair44 voxel; + if(z < perlinVal) + { + voxel.setMaterial(245); + voxel.setDensity(MaterialDensityPair44::getMaxDensity()); + } + else + { + voxel.setMaterial(0); + voxel.setDensity(MaterialDensityPair44::getMinDensity()); + } + + volData.setVoxelAt(x, y, z, voxel); + } + } + } +} + void createSphereInVolume(Volume& volData, Vector3DFloat v3dVolCenter, float fRadius) { //This vector hold the position of the center of the volume @@ -469,9 +502,10 @@ int main(int argc, char *argv[]) openGLWidget.show(); //Create an empty volume and then place a sphere in it - Volume volData(256, 256, 256); + Volume volData(1024, 1280, 256); //createSphereInVolume(volData, 30); - createPerlinVolumeFast(volData); + createPerlinTerrain(volData); + volData.setBlockCacheSize(8); /*srand(12345); for(int ct = 0; ct < 1000; ct++) @@ -487,12 +521,12 @@ int main(int argc, char *argv[]) }*/ //Extract the surface - SurfaceMesh mesh; + /*SurfaceMesh mesh; CubicSurfaceExtractorWithNormals surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); surfaceExtractor.execute(); //Pass the surface to the OpenGL window - openGLWidget.setSurfaceMeshToRender(mesh); + openGLWidget.setSurfaceMeshToRender(mesh);*/ //Run the message pump. return app.exec(); diff --git a/library/PolyVoxCore/include/PolyVoxImpl/Block.h b/library/PolyVoxCore/include/PolyVoxImpl/Block.h index 4a0bdce8..28cbf8dd 100644 --- a/library/PolyVoxCore/include/PolyVoxImpl/Block.h +++ b/library/PolyVoxCore/include/PolyVoxImpl/Block.h @@ -64,7 +64,7 @@ namespace PolyVox bool m_bIsUncompressedDataModified; uint64_t m_uTimestamp; - std::vector runlengths; + std::vector runlengths; std::vector values; }; } diff --git a/library/PolyVoxCore/include/PolyVoxImpl/Block.inl b/library/PolyVoxCore/include/PolyVoxImpl/Block.inl index fc86ed63..ff8572e9 100644 --- a/library/PolyVoxCore/include/PolyVoxImpl/Block.inl +++ b/library/PolyVoxCore/include/PolyVoxImpl/Block.inl @@ -208,6 +208,8 @@ namespace PolyVox template void Block::compress(void) { + assert(m_bIsCompressed == false); + //If the uncompressed data hasn't actually been //modified then we don't need to redo the compression. if(m_bIsUncompressedDataModified) @@ -217,12 +219,12 @@ namespace PolyVox values.clear(); VoxelType current = m_tUncompressedData[0]; - uint8_t runLength = 1; + uint16_t runLength = 1; for(uint32_t ct = 1; ct < uNoOfVoxels; ++ct) { VoxelType value = m_tUncompressedData[ct]; - if((value == current) && (runLength < (std::numeric_limits::max)())) + if((value == current) && (runLength < (std::numeric_limits::max)())) { runLength++; } @@ -245,6 +247,7 @@ namespace PolyVox //std::vector(values).swap(values); } + assert(m_tUncompressedData != 0); delete[] m_tUncompressedData; m_tUncompressedData = 0; m_bIsCompressed = true; @@ -253,6 +256,8 @@ namespace PolyVox template void Block::uncompress(void) { + assert(m_bIsCompressed == true); + assert(m_tUncompressedData == 0); m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength]; VoxelType* pUncompressedData = m_tUncompressedData; @@ -261,7 +266,7 @@ namespace PolyVox //on unsigned chars so is only possible if our voxel type is the right size. //Nore that memset takes an int type, but sonverts it to unsiogned char: //http://www.cplusplus.com/reference/clibrary/cstring/memset/ - if(sizeof(VoxelType) == sizeof(unsigned char)) + /*if(sizeof(VoxelType) == sizeof(unsigned char)) { for(uint32_t ct = 0; ct < runlengths.size(); ++ct) { @@ -271,7 +276,7 @@ namespace PolyVox } //Otherwise we fall back on a loop. else - { + {*/ for(uint32_t ct = 0; ct < runlengths.size(); ++ct) { for(uint32_t i = 0; i < runlengths[ct]; ++i) @@ -280,7 +285,7 @@ namespace PolyVox ++pUncompressedData; } } - } + //} m_bIsCompressed = false; m_bIsUncompressedDataModified = false; diff --git a/library/PolyVoxCore/include/Volume.h b/library/PolyVoxCore/include/Volume.h index 94157bb8..c00ef68b 100644 --- a/library/PolyVoxCore/include/Volume.h +++ b/library/PolyVoxCore/include/Volume.h @@ -120,7 +120,7 @@ namespace PolyVox public: ///Constructor - Volume(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength = 64); + Volume(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength = 32); ///Destructor ~Volume(); @@ -155,12 +155,16 @@ namespace PolyVox ///Resizes the volume to the specified dimensions void resize(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength = 32); + void setBlockCacheSize(uint16_t uBlockCacheSize); + void clearBlockCache(void); + public: Block* getUncompressedBlock(Block* block) const; Block m_pBorderBlock; std::vector< Block > m_pBlocks; mutable std::vector*> m_pUncompressedBlocks; + uint16_t m_uBlockCacheSize; uint32_t m_uNoOfBlocksInVolume; @@ -179,6 +183,9 @@ namespace PolyVox uint16_t m_uShortestSideLength; float m_fDiagonalLength; mutable uint64_t m_uTimestamper; + + mutable uint32_t m_uCompressions; + mutable uint32_t m_uUncompressions; }; //Some handy typedefs diff --git a/library/PolyVoxCore/include/Volume.inl b/library/PolyVoxCore/include/Volume.inl index 80b67c8f..269dbaca 100644 --- a/library/PolyVoxCore/include/Volume.inl +++ b/library/PolyVoxCore/include/Volume.inl @@ -49,7 +49,13 @@ namespace PolyVox template Volume::Volume(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength) :m_uTimestamper(0) + ,m_uBlockCacheSize(1024) + ,m_uCompressions(0) + ,m_uUncompressions(0) + ,m_uBlockSideLength(uBlockSideLength) { + setBlockCacheSize(m_uBlockCacheSize); + //Create a volume of the right size. resize(uWidth, uHeight, uDepth, uBlockSideLength); } @@ -262,6 +268,18 @@ namespace PolyVox return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } + template + void Volume::clearBlockCache(void) + { + for(uint32_t ct = 0; ct < m_pUncompressedBlocks.size(); ct++) + { + m_pUncompressedBlocks[ct]->compress(); + m_uCompressions++; + } + + m_pUncompressedBlocks.clear(); + } + //////////////////////////////////////////////////////////////////////////////// /// Note: Calling this function will destroy all existing data in the volume. /// \param uWidth The desired width in voxels. This must be a power of two. @@ -344,6 +362,14 @@ namespace PolyVox m_fDiagonalLength = sqrtf(static_cast(m_uWidth * m_uWidth + m_uHeight * m_uHeight + m_uDepth * m_uDepth)); } + template + void Volume::setBlockCacheSize(uint16_t uBlockCacheSize) + { + clearBlockCache(); + + m_uBlockCacheSize = uBlockCacheSize; + } + template Block* Volume::getUncompressedBlock(Block* block) const { @@ -354,8 +380,10 @@ namespace PolyVox return block; } - const uint32_t MaxUncompressedBlocks = 10; - if(m_pUncompressedBlocks.size() == MaxUncompressedBlocks) + uint32_t uUncompressedBlockIndex = 100000000; + + assert(m_pUncompressedBlocks.size() <= m_uBlockCacheSize); + if(m_pUncompressedBlocks.size() == m_uBlockCacheSize) { int32_t leastRecentlyUsedBlockIndex = -1; uint32_t uLeastRecentTimestamp = 1000000000000000; @@ -369,6 +397,7 @@ namespace PolyVox } m_pUncompressedBlocks[leastRecentlyUsedBlockIndex]->compress(); + m_uCompressions++; m_pUncompressedBlocks[leastRecentlyUsedBlockIndex] = block; } else @@ -377,6 +406,7 @@ namespace PolyVox } block->uncompress(); + m_uUncompressions++; return block; }