Index: library/PolyVoxCore/include/Volume.inl =================================================================== --- library/PolyVoxCore/include/Volume.inl (revision 1428) +++ library/PolyVoxCore/include/Volume.inl (working copy) @@ -376,6 +376,63 @@ } template + bool Volume::prefetchRegion(Region regPrefetch) + { + Vector3DInt32 start; + for(int i = 0; i < 3; i++) start.setElement(i, regPrefetch.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower); + Vector3DInt32 end; + for(int i = 0; i < 3; i++) end.setElement(i, regPrefetch.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower); + Vector3DInt32 size = end-start + Vector3DInt32(1,1,1); + int32_t numblocks = size.getX() * size.getY() * size.getZ(); + if(numblocks > m_uMaxNumberOfBlocksInMemory) { + return false; + } + if(numblocks > (m_uMaxNumberOfBlocksInMemory - m_pBlocks.size())) { + // TODO: unload enough blocks to support the blocks that will be loaded. + } + for(int32_t x = start.getX(); x <= end.getX(); x++) { + for(int32_t y = start.getY(); y <= end.getY(); y++) { + for(int32_t z = start.getZ(); z <= end.getZ(); z++) { + Block* block = getUncompressedBlock(x,y,z); + } + } + } + return true; + } + + template + uint32_t Volume::flushRegion(Region regFlush) + { + Vector3DInt32 start; + for(int i = 0; i < 3; i++) start.setElement(i, regFlush.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower); + Vector3DInt32 end; + for(int i = 0; i < 3; i++) end.setElement(i, regFlush.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower); + uint32_t count = 0; + for(int32_t x = start.getX(); x <= end.getX(); x++) { + for(int32_t y = start.getY(); y <= end.getY(); y++) { + for(int32_t z = start.getZ(); z <= end.getZ(); z++) { + Vector3DInt32 pos(x,y,z); + if(m_v3dLastAccessedBlockPos == pos) { + m_pLastAccessedBlock = NULL; + } + typename std::map::iterator itBlock = m_pBlocks.find(pos); + if(itBlock == m_pBlocks.end()) { + // not loaded, not unloading + continue; + } + eraseBlock(itBlock); + count++; + } + } + } + if(count > ((std::numeric_limits::max)() >> (m_uBlockSideLengthPower*3))) { + // eh, this will overflow... I have no idea what to do here + return (std::numeric_limits::max)(); + } + return count << (m_uBlockSideLengthPower*3); + } + + template void Volume::clearBlockCache(void) { for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) @@ -463,6 +520,22 @@ m_funcDataOverflowHandler(ConstVolumeProxy, reg); } + if(m_bCompressionEnabled) { + for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++) + { + // find the block in the uncompressed cache + if(m_vecUncompressedBlockCache[ct] == &(itBlock->second)) + { + // TODO: compression is unneccessary? or will not compressing this cause a memleak? + itBlock->second.block.compress(); + // put last object in cache here + m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back(); + // decrease cache size by one since last element is now in here twice + m_vecUncompressedBlockCache.resize(m_vecUncompressedBlockCache.size()-1); + break; + } + } + } m_pBlocks.erase(itBlock); } Index: library/PolyVoxCore/include/Volume.h =================================================================== --- library/PolyVoxCore/include/Volume.h (revision 1428) +++ library/PolyVoxCore/include/Volume.h (working copy) @@ -186,6 +186,17 @@ bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue); /// Sets the voxel at a 3D vector position bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue); + /// makes sure all the voxels in the given region are loaded + /// if MaxNumberOfBlocksInMemory is not large enough to support the region + /// this function will return false and the volume is unchanged + /// if all the voxels in the given region are already loaded, this function will not do anything but still return true. + /// other blocks might be unloaded to make space for the new blocks + bool prefetchRegion(Region regPrefetch); + /// attempts to unload all the voxels in the given region. + /// there is no guarantee that any voxels are unloaded + /// try unloading a region whose sidelengths are multiples of BlockSideLength + /// returns the number of voxels that were actually unloaded + uint32_t flushRegion(Region regFlush); void clearBlockCache(void); float calculateCompressionRatio(void); Index: examples/Basic/main.cpp =================================================================== --- examples/Basic/main.cpp (revision 1428) +++ examples/Basic/main.cpp (working copy) @@ -78,7 +78,7 @@ openGLWidget.show(); //Create an empty volume and then place a sphere in it - Volume volData(Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63))); + Volume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63))); createSphereInVolume(volData, 30); //Extract the surface Index: examples/OpenGL/main.cpp =================================================================== --- examples/OpenGL/main.cpp (revision 1428) +++ examples/OpenGL/main.cpp (working copy) @@ -72,7 +72,7 @@ int main(int argc, char *argv[]) { logHandler = &exampleLog; - Volume volData(Region(Vector3DInt32(0,0,0), Vector3DInt32(g_uVolumeSideLength-1, g_uVolumeSideLength-1, g_uVolumeSideLength-1))); + Volume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(g_uVolumeSideLength-1, g_uVolumeSideLength-1, g_uVolumeSideLength-1))); //Make our volume contain a sphere in the center. int32_t minPos = 0; Index: examples/Paging/main.cpp =================================================================== --- examples/Paging/main.cpp (revision 1428) +++ examples/Paging/main.cpp (working copy) @@ -250,7 +250,7 @@ openGLWidget.show(); //Create an empty volume and then place a sphere in it - Volume volData(&load, &unload, 128); + Volume volData(&load, &unload, 256); volData.setMaxNumberOfBlocksInMemory(4096); volData.setMaxNumberOfUncompressedBlocks(64); @@ -267,9 +267,21 @@ //createPerlinTerrain(volData); //createPerlinVolumeSlow(volData); std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl; + std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; //volData.setBlockCacheSize(64); + PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,1024,255)); + std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl; + volData.prefetchRegion(reg); std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl; std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; + PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(500,500,500)); + std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl; + uint32_t voxelsFlushed = volData.flushRegion(reg2); + Vector3DInt32 size = reg2.getUpperCorner() - reg2.getLowerCorner() + Vector3DInt32(1,1,1); + uint32_t voxelsFlushed2 = size.getX()*size.getY()*size.getZ(); + std::cout << voxelsFlushed << " Voxels were unloaded, while " << voxelsFlushed2 << " should have been unloaded" << std::endl; + std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl; + std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; /*srand(12345); for(int ct = 0; ct < 1000; ct++) @@ -287,7 +299,6 @@ //Extract the surface SurfaceMesh mesh; //CubicSurfaceExtractorWithNormals surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); - PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,1024,255)); SurfaceExtractor surfaceExtractor(&volData, reg, &mesh); //CubicSurfaceExtractorWithNormals surfaceExtractor(&volData, reg, &mesh); surfaceExtractor.execute();