Deprecated old serialization functions.
Added new serialization functions which support versioning. Added 'resize()' function to volume.
This commit is contained in:
@ -156,6 +156,8 @@ namespace PolyVox
|
|||||||
///Sets the voxel at a 3D vector position
|
///Sets the voxel at a 3D vector position
|
||||||
bool setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
bool setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||||
|
|
||||||
|
///Resises the volume to the specified dimensions
|
||||||
|
void resize(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength = 32);
|
||||||
void tidyUpMemory(uint32_t uNoOfBlocksToProcess = (std::numeric_limits<uint32_t>::max)());
|
void tidyUpMemory(uint32_t uNoOfBlocksToProcess = (std::numeric_limits<uint32_t>::max)());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -48,87 +48,19 @@ namespace PolyVox
|
|||||||
/// blocks are more likely to be homogeneous (so more easily shared) and have better
|
/// blocks are more likely to be homogeneous (so more easily shared) and have better
|
||||||
/// cache behaviour. However, there is a memory overhead per block so if they are
|
/// cache behaviour. However, there is a memory overhead per block so if they are
|
||||||
/// not shared it could actually be less efficient (this will depend on the data).
|
/// not shared it could actually be less efficient (this will depend on the data).
|
||||||
/// The size of the volume may also be a factor when choosing block size. Specifying
|
/// The size of the volume may also be a factor when choosing block size. Accept
|
||||||
/// '0' for the block side length will cause the blocks to be as large as possible,
|
/// the default if you are not sure what to choose here.
|
||||||
/// which will basically be the length of the shortest side. Accept the default if
|
|
||||||
/// you are not sure what to choose here.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
Volume<VoxelType>::Volume(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength)
|
Volume<VoxelType>::Volume(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength)
|
||||||
:m_pBlocks(0)
|
|
||||||
,m_uCurrentBlockForTidying(0)
|
|
||||||
{
|
{
|
||||||
//A values of zero for a block side length is a special value to indicate
|
//Create a volume of the right size.
|
||||||
//that the block side length should simply be made as large as possible.
|
resize(uWidth, uHeight, uDepth, uBlockSideLength);
|
||||||
if(uBlockSideLength == 0)
|
|
||||||
{
|
|
||||||
uBlockSideLength = (std::min)((std::min)(uWidth,uHeight),uDepth);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Debug mode validation
|
|
||||||
assert(isPowerOf2(uBlockSideLength));
|
|
||||||
assert(uBlockSideLength <= uWidth);
|
|
||||||
assert(uBlockSideLength <= uHeight);
|
|
||||||
assert(uBlockSideLength <= uDepth);
|
|
||||||
|
|
||||||
//Release mode validation
|
|
||||||
if(!isPowerOf2(uBlockSideLength))
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("Block side length must be a power of two.");
|
|
||||||
}
|
|
||||||
if(uBlockSideLength > uWidth)
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("Block side length cannot be greater than volume width.");
|
|
||||||
}
|
|
||||||
if(uBlockSideLength > uHeight)
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("Block side length cannot be greater than volume height.");
|
|
||||||
}
|
|
||||||
if(uBlockSideLength > uDepth)
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("Block side length cannot be greater than volume depth.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Compute the volume side lengths
|
|
||||||
m_uWidth = uWidth;
|
|
||||||
//m_uWidthPower = logBase2(m_uWidth);
|
|
||||||
|
|
||||||
m_uHeight = uHeight;
|
|
||||||
//m_uHeightPower = logBase2(m_uHeight);
|
|
||||||
|
|
||||||
m_uDepth = uDepth;
|
|
||||||
//m_uDepthPower = logBase2(m_uDepth);
|
|
||||||
|
|
||||||
//Compute the block side length
|
|
||||||
m_uBlockSideLength = uBlockSideLength;
|
|
||||||
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
|
||||||
|
|
||||||
//Compute the side lengths in blocks
|
|
||||||
m_uWidthInBlocks = m_uWidth / m_uBlockSideLength;
|
|
||||||
m_uHeightInBlocks = m_uHeight / m_uBlockSideLength;
|
|
||||||
m_uDepthInBlocks = m_uDepth / m_uBlockSideLength;
|
|
||||||
|
|
||||||
//Compute number of blocks in the volume
|
|
||||||
m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
|
|
||||||
|
|
||||||
//Create the blocks
|
|
||||||
m_pBlocks.resize(m_uNoOfBlocksInVolume);
|
|
||||||
m_vecBlockIsPotentiallyHomogenous.resize(m_uNoOfBlocksInVolume);
|
|
||||||
for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
|
|
||||||
{
|
|
||||||
m_pBlocks[i] = getHomogenousBlock(VoxelType());
|
|
||||||
m_vecBlockIsPotentiallyHomogenous[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create the border block
|
//Create the border block
|
||||||
polyvox_shared_ptr< Block<VoxelType> > pTempBlock(new Block<VoxelType>(m_uBlockSideLength));
|
polyvox_shared_ptr< Block<VoxelType> > pTempBlock(new Block<VoxelType>(m_uBlockSideLength));
|
||||||
pTempBlock->fill(VoxelType());
|
pTempBlock->fill(VoxelType());
|
||||||
m_pBorderBlock = pTempBlock;
|
m_pBorderBlock = pTempBlock;
|
||||||
|
|
||||||
//Other properties we might find useful later
|
|
||||||
m_uLongestSideLength = (std::max)((std::max)(m_uWidth,m_uHeight),m_uDepth);
|
|
||||||
m_uShortestSideLength = (std::min)((std::min)(m_uWidth,m_uHeight),m_uDepth);
|
|
||||||
m_fDiagonalLength = sqrtf(static_cast<float>(m_uWidth * m_uWidth + m_uHeight * m_uHeight + m_uDepth * m_uDepth));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -361,6 +293,91 @@ namespace PolyVox
|
|||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Other
|
#pragma region Other
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// 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.
|
||||||
|
/// \param uHeight The desired height in voxels. This must be a power of two.
|
||||||
|
/// \param uDepth The desired depth in voxels. This must be a power of two.
|
||||||
|
/// \param uBlockSideLength The size of the blocks which make up the volume. Small
|
||||||
|
/// blocks are more likely to be homogeneous (so more easily shared) and have better
|
||||||
|
/// cache behaviour. However, there is a memory overhead per block so if they are
|
||||||
|
/// not shared it could actually be less efficient (this will depend on the data).
|
||||||
|
/// The size of the volume may also be a factor when choosing block size. Accept
|
||||||
|
/// the default if you are not sure what to choose here.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <typename VoxelType>
|
||||||
|
void Volume<VoxelType>::resize(uint16_t uWidth, uint16_t uHeight, uint16_t uDepth, uint16_t uBlockSideLength)
|
||||||
|
{
|
||||||
|
//Debug mode validation
|
||||||
|
assert(uBlockSideLength > 0);
|
||||||
|
assert(isPowerOf2(uBlockSideLength));
|
||||||
|
assert(uBlockSideLength <= uWidth);
|
||||||
|
assert(uBlockSideLength <= uHeight);
|
||||||
|
assert(uBlockSideLength <= uDepth);
|
||||||
|
|
||||||
|
//Release mode validation
|
||||||
|
if(uBlockSideLength == 0)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Block side length cannot be zero.");
|
||||||
|
}
|
||||||
|
if(!isPowerOf2(uBlockSideLength))
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Block side length must be a power of two.");
|
||||||
|
}
|
||||||
|
if(uBlockSideLength > uWidth)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Block side length cannot be greater than volume width.");
|
||||||
|
}
|
||||||
|
if(uBlockSideLength > uHeight)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Block side length cannot be greater than volume height.");
|
||||||
|
}
|
||||||
|
if(uBlockSideLength > uDepth)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Block side length cannot be greater than volume depth.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Empty the previous data
|
||||||
|
m_pBlocks.empty();
|
||||||
|
m_vecBlockIsPotentiallyHomogenous.empty();
|
||||||
|
m_pHomogenousBlock.empty();
|
||||||
|
|
||||||
|
//Compute the volume side lengths
|
||||||
|
m_uWidth = uWidth;
|
||||||
|
m_uHeight = uHeight;
|
||||||
|
m_uDepth = uDepth;
|
||||||
|
|
||||||
|
//Compute the block side length
|
||||||
|
m_uBlockSideLength = uBlockSideLength;
|
||||||
|
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
||||||
|
|
||||||
|
//Compute the side lengths in blocks
|
||||||
|
m_uWidthInBlocks = m_uWidth / m_uBlockSideLength;
|
||||||
|
m_uHeightInBlocks = m_uHeight / m_uBlockSideLength;
|
||||||
|
m_uDepthInBlocks = m_uDepth / m_uBlockSideLength;
|
||||||
|
|
||||||
|
//Compute number of blocks in the volume
|
||||||
|
m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
|
||||||
|
|
||||||
|
//Create the blocks
|
||||||
|
m_pBlocks.resize(m_uNoOfBlocksInVolume);
|
||||||
|
m_vecBlockIsPotentiallyHomogenous.resize(m_uNoOfBlocksInVolume);
|
||||||
|
for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
|
||||||
|
{
|
||||||
|
m_pBlocks[i] = getHomogenousBlock(VoxelType());
|
||||||
|
m_vecBlockIsPotentiallyHomogenous[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Other properties we might find useful later
|
||||||
|
m_uLongestSideLength = (std::max)((std::max)(m_uWidth,m_uHeight),m_uDepth);
|
||||||
|
m_uShortestSideLength = (std::min)((std::min)(m_uWidth,m_uHeight),m_uDepth);
|
||||||
|
m_fDiagonalLength = sqrtf(static_cast<float>(m_uWidth * m_uWidth + m_uHeight * m_uHeight + m_uDepth * m_uDepth));
|
||||||
|
|
||||||
|
//Reset the counter for tidying
|
||||||
|
m_uCurrentBlockForTidying = 0;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Clean up the memory usage of the volume. Checks for any blocks which are
|
/// Clean up the memory usage of the volume. Checks for any blocks which are
|
||||||
/// homogeneous and flags them as such for faster processing and reduced memory
|
/// homogeneous and flags them as such for faster processing and reduced memory
|
||||||
|
@ -41,6 +41,9 @@ namespace PolyVox
|
|||||||
virtual void onProgressUpdated(float fProgress) = 0;
|
virtual void onProgressUpdated(float fProgress) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// THESE FUNCTIONS ARE DEPRECATED. USE VERSIONED 'loadVolume' AND 'saveVolume' INSTEAD.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0);
|
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0);
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
@ -50,6 +53,20 @@ namespace PolyVox
|
|||||||
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0);
|
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0);
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void saveVolumeRle(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener = 0);
|
void saveVolumeRle(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// END OF DEPRECATED FUNCTIONS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool loadVolume(std::istream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool saveVolume(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool loadVersion0(std::istream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool saveVersion0(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "Serialization.inl"
|
#include "Serialization.inl"
|
||||||
|
@ -32,6 +32,8 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener)
|
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener)
|
||||||
{
|
{
|
||||||
|
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP.
|
||||||
|
|
||||||
//Read volume dimensions
|
//Read volume dimensions
|
||||||
uint8_t volumeWidthPower = 0;
|
uint8_t volumeWidthPower = 0;
|
||||||
uint8_t volumeHeightPower = 0;
|
uint8_t volumeHeightPower = 0;
|
||||||
@ -81,6 +83,8 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void saveVolumeRaw(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
void saveVolumeRaw(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
||||||
{
|
{
|
||||||
|
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP.
|
||||||
|
|
||||||
//Write volume dimensions
|
//Write volume dimensions
|
||||||
uint16_t volumeWidth = volume.getWidth();
|
uint16_t volumeWidth = volume.getWidth();
|
||||||
uint16_t volumeHeight = volume.getHeight();
|
uint16_t volumeHeight = volume.getHeight();
|
||||||
@ -128,6 +132,8 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener)
|
polyvox_shared_ptr< Volume<VoxelType> > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener)
|
||||||
{
|
{
|
||||||
|
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP.
|
||||||
|
|
||||||
//Read volume dimensions
|
//Read volume dimensions
|
||||||
uint8_t volumeWidthPower = 0;
|
uint8_t volumeWidthPower = 0;
|
||||||
uint8_t volumeHeightPower = 0;
|
uint8_t volumeHeightPower = 0;
|
||||||
@ -191,6 +197,8 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void saveVolumeRle(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
void saveVolumeRle(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
||||||
{
|
{
|
||||||
|
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP.
|
||||||
|
|
||||||
//Write volume dimensions
|
//Write volume dimensions
|
||||||
uint16_t volumeWidth = volume.getWidth();
|
uint16_t volumeWidth = volume.getWidth();
|
||||||
uint16_t volumeHeight = volume.getHeight();
|
uint16_t volumeHeight = volume.getHeight();
|
||||||
@ -256,4 +264,173 @@ namespace PolyVox
|
|||||||
progressListener->onProgressUpdated(1.0f);
|
progressListener->onProgressUpdated(1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// New version of load/save code with versioning
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool loadVolume(std::istream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
||||||
|
{
|
||||||
|
char pIdentifier[8];
|
||||||
|
stream.read(pIdentifier, 7);
|
||||||
|
pIdentifier[7] = '\0'; //Set the null terminator
|
||||||
|
if(strcmp(pIdentifier, "PolyVox") != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t uVersion;
|
||||||
|
stream.read(reinterpret_cast<char*>(&uVersion), sizeof(uVersion));
|
||||||
|
|
||||||
|
switch(uVersion)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return loadVersion0(stream, volume, progressListener);
|
||||||
|
//Return means no need to break...
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool saveVolume(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
||||||
|
{
|
||||||
|
char pIdentifier[] = "PolyVox";
|
||||||
|
stream.write(pIdentifier, 7);
|
||||||
|
|
||||||
|
uint16_t uVersion = 0;
|
||||||
|
stream.write(reinterpret_cast<const char*>(&uVersion), sizeof(uVersion));
|
||||||
|
|
||||||
|
return saveVersion0(stream, volume, progressListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller.
|
||||||
|
//FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool loadVersion0(std::istream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
||||||
|
{
|
||||||
|
//Read volume dimensions
|
||||||
|
uint16_t volumeWidth = 0;
|
||||||
|
uint16_t volumeHeight = 0;
|
||||||
|
uint16_t volumeDepth = 0;
|
||||||
|
stream.read(reinterpret_cast<char*>(&volumeWidth), sizeof(volumeWidth));
|
||||||
|
stream.read(reinterpret_cast<char*>(&volumeHeight), sizeof(volumeHeight));
|
||||||
|
stream.read(reinterpret_cast<char*>(&volumeDepth), sizeof(volumeDepth));
|
||||||
|
|
||||||
|
//Resize the volume
|
||||||
|
volume.resize(volumeWidth, volumeHeight, volumeDepth);
|
||||||
|
|
||||||
|
//Read data
|
||||||
|
bool firstTime = true;
|
||||||
|
uint32_t runLength = 0;
|
||||||
|
VoxelType value;
|
||||||
|
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||||
|
stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||||
|
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||||
|
{
|
||||||
|
//Update progress once per slice.
|
||||||
|
if(progressListener)
|
||||||
|
{
|
||||||
|
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||||
|
progressListener->onProgressUpdated(fProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||||
|
{
|
||||||
|
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||||
|
{
|
||||||
|
if(runLength != 0)
|
||||||
|
{
|
||||||
|
volume.setVoxelAt(x,y,z,value);
|
||||||
|
runLength--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||||
|
stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||||
|
|
||||||
|
volume.setVoxelAt(x,y,z,value);
|
||||||
|
runLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Finished
|
||||||
|
if(progressListener)
|
||||||
|
{
|
||||||
|
progressListener->onProgressUpdated(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
bool saveVersion0(std::ostream& stream, Volume<VoxelType>& volume, VolumeSerializationProgressListener* progressListener)
|
||||||
|
{
|
||||||
|
//Write volume dimensions
|
||||||
|
uint16_t volumeWidth = volume.getWidth();
|
||||||
|
uint16_t volumeHeight = volume.getHeight();
|
||||||
|
uint16_t volumeDepth = volume.getDepth();
|
||||||
|
|
||||||
|
stream.write(reinterpret_cast<char*>(&volumeWidth), sizeof(volumeWidth));
|
||||||
|
stream.write(reinterpret_cast<char*>(&volumeHeight), sizeof(volumeHeight));
|
||||||
|
stream.write(reinterpret_cast<char*>(&volumeDepth), sizeof(volumeDepth));
|
||||||
|
|
||||||
|
//Write data
|
||||||
|
VolumeSampler<VoxelType> volIter(&volume);
|
||||||
|
VoxelType current;
|
||||||
|
uint32_t runLength = 0;
|
||||||
|
bool firstTime = true;
|
||||||
|
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||||
|
{
|
||||||
|
//Update progress once per slice.
|
||||||
|
if(progressListener)
|
||||||
|
{
|
||||||
|
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||||
|
progressListener->onProgressUpdated(fProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||||
|
{
|
||||||
|
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||||
|
{
|
||||||
|
volIter.setPosition(x,y,z);
|
||||||
|
VoxelType value = volIter.getVoxel();
|
||||||
|
if(firstTime)
|
||||||
|
{
|
||||||
|
current = value;
|
||||||
|
runLength = 1;
|
||||||
|
firstTime = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(value == current)
|
||||||
|
{
|
||||||
|
runLength++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream.write(reinterpret_cast<char*>(¤t), sizeof(current));
|
||||||
|
stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||||
|
current = value;
|
||||||
|
runLength = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.write(reinterpret_cast<char*>(¤t), sizeof(current));
|
||||||
|
stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||||
|
|
||||||
|
//Finished
|
||||||
|
if(progressListener)
|
||||||
|
{
|
||||||
|
progressListener->onProgressUpdated(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user