From d99ed5e624d3b42fb284886988bfaaa643e48f01 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 28 Mar 2015 09:46:05 +0100 Subject: [PATCH] Implemented morton encoding using standard bit-twidling approach. --- include/PolyVox/PagedVolume.h | 4 ++-- include/PolyVox/PagedVolumeChunk.inl | 35 +++++++++++++++++----------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/include/PolyVox/PagedVolume.h b/include/PolyVox/PagedVolume.h index c4e306ed..0eb87a30 100644 --- a/include/PolyVox/PagedVolume.h +++ b/include/PolyVox/PagedVolume.h @@ -127,10 +127,10 @@ namespace PolyVox VoxelType* getData(void) const; uint32_t getDataSizeInBytes(void) const; - VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const; + VoxelType getVoxel(uint32_t uXPos, uint32_t uYPos, uint32_t uZPos) const; VoxelType getVoxel(const Vector3DUint16& v3dPos) const; - void setVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); + void setVoxel(uint32_t uXPos, uint32_t uYPos, uint32_t uZPos, VoxelType tValue); void setVoxel(const Vector3DUint16& v3dPos, VoxelType tValue); private: diff --git a/include/PolyVox/PagedVolumeChunk.inl b/include/PolyVox/PagedVolumeChunk.inl index 51003201..33484f0e 100644 --- a/include/PolyVox/PagedVolumeChunk.inl +++ b/include/PolyVox/PagedVolumeChunk.inl @@ -91,8 +91,19 @@ namespace PolyVox return m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType); } + // Based on https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/ + inline uint32_t Part1By2(uint32_t x) + { + x &= 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210 + x = (x ^ (x << 16)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210 + x = (x ^ (x << 8)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210 + x = (x ^ (x << 4)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10 + x = (x ^ (x << 2)) & 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0 + return x; + } + template - VoxelType PagedVolume::Chunk::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const + VoxelType PagedVolume::Chunk::getVoxel(uint32_t uXPos, uint32_t uYPos, uint32_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. @@ -101,12 +112,10 @@ namespace PolyVox POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the chunk"); POLYVOX_ASSERT(m_tData, "No uncompressed data - chunk must be decompressed before accessing voxels."); - return m_tData - [ - uXPos + - uYPos * m_uSideLength + - uZPos * m_uSideLength * m_uSideLength - ]; + uint32_t index = 0; + index |= Part1By2(uXPos) | Part1By2(uYPos) << 1 | Part1By2(uZPos) << 2; + + return m_tData[index]; } template @@ -116,7 +125,7 @@ namespace PolyVox } template - void PagedVolume::Chunk::setVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue) + void PagedVolume::Chunk::setVoxel(uint32_t uXPos, uint32_t uYPos, uint32_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. @@ -125,12 +134,10 @@ namespace PolyVox POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the chunk"); POLYVOX_ASSERT(m_tData, "No uncompressed data - chunk must be decompressed before accessing voxels."); - m_tData - [ - uXPos + - uYPos * m_uSideLength + - uZPos * m_uSideLength * m_uSideLength - ] = tValue; + uint32_t index = 0; + index |= Part1By2(uXPos) | Part1By2(uYPos) << 1 | Part1By2(uZPos) << 2; + + m_tData[index] = tValue; this->m_bDataModified = true; }