Merge branch 'feature/morton-encoding' into develop

This commit is contained in:
David Williams 2015-04-05 17:44:27 +02:00
commit 27a59f34bc
5 changed files with 359 additions and 135 deletions

View File

@ -0,0 +1,159 @@
/*******************************************************************************
Copyright (c) 2005-20015 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_Morton_H__
#define __PolyVox_Morton_H__
namespace PolyVox
{
// Based on: http://www.forceflow.be/2013/10/07/morton-encodingdecoding-through-bit-interleaving-implementations/
static const uint32_t morton256_x[256] =
{
0x00000000,
0x00000001, 0x00000008, 0x00000009, 0x00000040, 0x00000041, 0x00000048, 0x00000049, 0x00000200,
0x00000201, 0x00000208, 0x00000209, 0x00000240, 0x00000241, 0x00000248, 0x00000249, 0x00001000,
0x00001001, 0x00001008, 0x00001009, 0x00001040, 0x00001041, 0x00001048, 0x00001049, 0x00001200,
0x00001201, 0x00001208, 0x00001209, 0x00001240, 0x00001241, 0x00001248, 0x00001249, 0x00008000,
0x00008001, 0x00008008, 0x00008009, 0x00008040, 0x00008041, 0x00008048, 0x00008049, 0x00008200,
0x00008201, 0x00008208, 0x00008209, 0x00008240, 0x00008241, 0x00008248, 0x00008249, 0x00009000,
0x00009001, 0x00009008, 0x00009009, 0x00009040, 0x00009041, 0x00009048, 0x00009049, 0x00009200,
0x00009201, 0x00009208, 0x00009209, 0x00009240, 0x00009241, 0x00009248, 0x00009249, 0x00040000,
0x00040001, 0x00040008, 0x00040009, 0x00040040, 0x00040041, 0x00040048, 0x00040049, 0x00040200,
0x00040201, 0x00040208, 0x00040209, 0x00040240, 0x00040241, 0x00040248, 0x00040249, 0x00041000,
0x00041001, 0x00041008, 0x00041009, 0x00041040, 0x00041041, 0x00041048, 0x00041049, 0x00041200,
0x00041201, 0x00041208, 0x00041209, 0x00041240, 0x00041241, 0x00041248, 0x00041249, 0x00048000,
0x00048001, 0x00048008, 0x00048009, 0x00048040, 0x00048041, 0x00048048, 0x00048049, 0x00048200,
0x00048201, 0x00048208, 0x00048209, 0x00048240, 0x00048241, 0x00048248, 0x00048249, 0x00049000,
0x00049001, 0x00049008, 0x00049009, 0x00049040, 0x00049041, 0x00049048, 0x00049049, 0x00049200,
0x00049201, 0x00049208, 0x00049209, 0x00049240, 0x00049241, 0x00049248, 0x00049249, 0x00200000,
0x00200001, 0x00200008, 0x00200009, 0x00200040, 0x00200041, 0x00200048, 0x00200049, 0x00200200,
0x00200201, 0x00200208, 0x00200209, 0x00200240, 0x00200241, 0x00200248, 0x00200249, 0x00201000,
0x00201001, 0x00201008, 0x00201009, 0x00201040, 0x00201041, 0x00201048, 0x00201049, 0x00201200,
0x00201201, 0x00201208, 0x00201209, 0x00201240, 0x00201241, 0x00201248, 0x00201249, 0x00208000,
0x00208001, 0x00208008, 0x00208009, 0x00208040, 0x00208041, 0x00208048, 0x00208049, 0x00208200,
0x00208201, 0x00208208, 0x00208209, 0x00208240, 0x00208241, 0x00208248, 0x00208249, 0x00209000,
0x00209001, 0x00209008, 0x00209009, 0x00209040, 0x00209041, 0x00209048, 0x00209049, 0x00209200,
0x00209201, 0x00209208, 0x00209209, 0x00209240, 0x00209241, 0x00209248, 0x00209249, 0x00240000,
0x00240001, 0x00240008, 0x00240009, 0x00240040, 0x00240041, 0x00240048, 0x00240049, 0x00240200,
0x00240201, 0x00240208, 0x00240209, 0x00240240, 0x00240241, 0x00240248, 0x00240249, 0x00241000,
0x00241001, 0x00241008, 0x00241009, 0x00241040, 0x00241041, 0x00241048, 0x00241049, 0x00241200,
0x00241201, 0x00241208, 0x00241209, 0x00241240, 0x00241241, 0x00241248, 0x00241249, 0x00248000,
0x00248001, 0x00248008, 0x00248009, 0x00248040, 0x00248041, 0x00248048, 0x00248049, 0x00248200,
0x00248201, 0x00248208, 0x00248209, 0x00248240, 0x00248241, 0x00248248, 0x00248249, 0x00249000,
0x00249001, 0x00249008, 0x00249009, 0x00249040, 0x00249041, 0x00249048, 0x00249049, 0x00249200,
0x00249201, 0x00249208, 0x00249209, 0x00249240, 0x00249241, 0x00249248, 0x00249249
};
// pre-shifted table for Y coordinates (1 bit to the left)
static const uint32_t morton256_y[256] = {
0x00000000,
0x00000002, 0x00000010, 0x00000012, 0x00000080, 0x00000082, 0x00000090, 0x00000092, 0x00000400,
0x00000402, 0x00000410, 0x00000412, 0x00000480, 0x00000482, 0x00000490, 0x00000492, 0x00002000,
0x00002002, 0x00002010, 0x00002012, 0x00002080, 0x00002082, 0x00002090, 0x00002092, 0x00002400,
0x00002402, 0x00002410, 0x00002412, 0x00002480, 0x00002482, 0x00002490, 0x00002492, 0x00010000,
0x00010002, 0x00010010, 0x00010012, 0x00010080, 0x00010082, 0x00010090, 0x00010092, 0x00010400,
0x00010402, 0x00010410, 0x00010412, 0x00010480, 0x00010482, 0x00010490, 0x00010492, 0x00012000,
0x00012002, 0x00012010, 0x00012012, 0x00012080, 0x00012082, 0x00012090, 0x00012092, 0x00012400,
0x00012402, 0x00012410, 0x00012412, 0x00012480, 0x00012482, 0x00012490, 0x00012492, 0x00080000,
0x00080002, 0x00080010, 0x00080012, 0x00080080, 0x00080082, 0x00080090, 0x00080092, 0x00080400,
0x00080402, 0x00080410, 0x00080412, 0x00080480, 0x00080482, 0x00080490, 0x00080492, 0x00082000,
0x00082002, 0x00082010, 0x00082012, 0x00082080, 0x00082082, 0x00082090, 0x00082092, 0x00082400,
0x00082402, 0x00082410, 0x00082412, 0x00082480, 0x00082482, 0x00082490, 0x00082492, 0x00090000,
0x00090002, 0x00090010, 0x00090012, 0x00090080, 0x00090082, 0x00090090, 0x00090092, 0x00090400,
0x00090402, 0x00090410, 0x00090412, 0x00090480, 0x00090482, 0x00090490, 0x00090492, 0x00092000,
0x00092002, 0x00092010, 0x00092012, 0x00092080, 0x00092082, 0x00092090, 0x00092092, 0x00092400,
0x00092402, 0x00092410, 0x00092412, 0x00092480, 0x00092482, 0x00092490, 0x00092492, 0x00400000,
0x00400002, 0x00400010, 0x00400012, 0x00400080, 0x00400082, 0x00400090, 0x00400092, 0x00400400,
0x00400402, 0x00400410, 0x00400412, 0x00400480, 0x00400482, 0x00400490, 0x00400492, 0x00402000,
0x00402002, 0x00402010, 0x00402012, 0x00402080, 0x00402082, 0x00402090, 0x00402092, 0x00402400,
0x00402402, 0x00402410, 0x00402412, 0x00402480, 0x00402482, 0x00402490, 0x00402492, 0x00410000,
0x00410002, 0x00410010, 0x00410012, 0x00410080, 0x00410082, 0x00410090, 0x00410092, 0x00410400,
0x00410402, 0x00410410, 0x00410412, 0x00410480, 0x00410482, 0x00410490, 0x00410492, 0x00412000,
0x00412002, 0x00412010, 0x00412012, 0x00412080, 0x00412082, 0x00412090, 0x00412092, 0x00412400,
0x00412402, 0x00412410, 0x00412412, 0x00412480, 0x00412482, 0x00412490, 0x00412492, 0x00480000,
0x00480002, 0x00480010, 0x00480012, 0x00480080, 0x00480082, 0x00480090, 0x00480092, 0x00480400,
0x00480402, 0x00480410, 0x00480412, 0x00480480, 0x00480482, 0x00480490, 0x00480492, 0x00482000,
0x00482002, 0x00482010, 0x00482012, 0x00482080, 0x00482082, 0x00482090, 0x00482092, 0x00482400,
0x00482402, 0x00482410, 0x00482412, 0x00482480, 0x00482482, 0x00482490, 0x00482492, 0x00490000,
0x00490002, 0x00490010, 0x00490012, 0x00490080, 0x00490082, 0x00490090, 0x00490092, 0x00490400,
0x00490402, 0x00490410, 0x00490412, 0x00490480, 0x00490482, 0x00490490, 0x00490492, 0x00492000,
0x00492002, 0x00492010, 0x00492012, 0x00492080, 0x00492082, 0x00492090, 0x00492092, 0x00492400,
0x00492402, 0x00492410, 0x00492412, 0x00492480, 0x00492482, 0x00492490, 0x00492492
};
// Pre-shifted table for z (2 bits to the left)
static const uint32_t morton256_z[256] = {
0x00000000,
0x00000004, 0x00000020, 0x00000024, 0x00000100, 0x00000104, 0x00000120, 0x00000124, 0x00000800,
0x00000804, 0x00000820, 0x00000824, 0x00000900, 0x00000904, 0x00000920, 0x00000924, 0x00004000,
0x00004004, 0x00004020, 0x00004024, 0x00004100, 0x00004104, 0x00004120, 0x00004124, 0x00004800,
0x00004804, 0x00004820, 0x00004824, 0x00004900, 0x00004904, 0x00004920, 0x00004924, 0x00020000,
0x00020004, 0x00020020, 0x00020024, 0x00020100, 0x00020104, 0x00020120, 0x00020124, 0x00020800,
0x00020804, 0x00020820, 0x00020824, 0x00020900, 0x00020904, 0x00020920, 0x00020924, 0x00024000,
0x00024004, 0x00024020, 0x00024024, 0x00024100, 0x00024104, 0x00024120, 0x00024124, 0x00024800,
0x00024804, 0x00024820, 0x00024824, 0x00024900, 0x00024904, 0x00024920, 0x00024924, 0x00100000,
0x00100004, 0x00100020, 0x00100024, 0x00100100, 0x00100104, 0x00100120, 0x00100124, 0x00100800,
0x00100804, 0x00100820, 0x00100824, 0x00100900, 0x00100904, 0x00100920, 0x00100924, 0x00104000,
0x00104004, 0x00104020, 0x00104024, 0x00104100, 0x00104104, 0x00104120, 0x00104124, 0x00104800,
0x00104804, 0x00104820, 0x00104824, 0x00104900, 0x00104904, 0x00104920, 0x00104924, 0x00120000,
0x00120004, 0x00120020, 0x00120024, 0x00120100, 0x00120104, 0x00120120, 0x00120124, 0x00120800,
0x00120804, 0x00120820, 0x00120824, 0x00120900, 0x00120904, 0x00120920, 0x00120924, 0x00124000,
0x00124004, 0x00124020, 0x00124024, 0x00124100, 0x00124104, 0x00124120, 0x00124124, 0x00124800,
0x00124804, 0x00124820, 0x00124824, 0x00124900, 0x00124904, 0x00124920, 0x00124924, 0x00800000,
0x00800004, 0x00800020, 0x00800024, 0x00800100, 0x00800104, 0x00800120, 0x00800124, 0x00800800,
0x00800804, 0x00800820, 0x00800824, 0x00800900, 0x00800904, 0x00800920, 0x00800924, 0x00804000,
0x00804004, 0x00804020, 0x00804024, 0x00804100, 0x00804104, 0x00804120, 0x00804124, 0x00804800,
0x00804804, 0x00804820, 0x00804824, 0x00804900, 0x00804904, 0x00804920, 0x00804924, 0x00820000,
0x00820004, 0x00820020, 0x00820024, 0x00820100, 0x00820104, 0x00820120, 0x00820124, 0x00820800,
0x00820804, 0x00820820, 0x00820824, 0x00820900, 0x00820904, 0x00820920, 0x00820924, 0x00824000,
0x00824004, 0x00824020, 0x00824024, 0x00824100, 0x00824104, 0x00824120, 0x00824124, 0x00824800,
0x00824804, 0x00824820, 0x00824824, 0x00824900, 0x00824904, 0x00824920, 0x00824924, 0x00900000,
0x00900004, 0x00900020, 0x00900024, 0x00900100, 0x00900104, 0x00900120, 0x00900124, 0x00900800,
0x00900804, 0x00900820, 0x00900824, 0x00900900, 0x00900904, 0x00900920, 0x00900924, 0x00904000,
0x00904004, 0x00904020, 0x00904024, 0x00904100, 0x00904104, 0x00904120, 0x00904124, 0x00904800,
0x00904804, 0x00904820, 0x00904824, 0x00904900, 0x00904904, 0x00904920, 0x00904924, 0x00920000,
0x00920004, 0x00920020, 0x00920024, 0x00920100, 0x00920104, 0x00920120, 0x00920124, 0x00920800,
0x00920804, 0x00920820, 0x00920824, 0x00920900, 0x00920904, 0x00920920, 0x00920924, 0x00924000,
0x00924004, 0x00924020, 0x00924024, 0x00924100, 0x00924104, 0x00924120, 0x00924124, 0x00924800,
0x00924804, 0x00924820, 0x00924824, 0x00924900, 0x00924904, 0x00924920, 0x00924924
};
/*inline uint32_t convertCoordinates(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos)
{
uint64_t answer = 0;
answer = morton256_z[(uZPos >> 16) & 0xFF] | // we start by shifting the third byte, since we only look at the first 21 bits
morton256_y[(uYPos >> 16) & 0xFF] |
morton256_x[(uXPos >> 16) & 0xFF];
answer = answer << 48 |
morton256_z[(uZPos >> 8) & 0xFF] | // shifting second byte
morton256_y[(uYPos >> 8) & 0xFF] |
morton256_x[(uXPos >> 8) & 0xFF];
answer = answer << 24 |
morton256_z[(uZPos)& 0xFF] | // first byte
morton256_y[(uYPos)& 0xFF] |
morton256_x[(uXPos)& 0xFF];
return answer;
}*/
}
#endif //__PolyVox_Morton_H__

View File

@ -127,12 +127,15 @@ namespace PolyVox
VoxelType* getData(void) const; VoxelType* getData(void) const;
uint32_t getDataSizeInBytes(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; 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); void setVoxel(const Vector3DUint16& v3dPos, VoxelType tValue);
void changeLinearOrderingToMorton(void);
void changeMortonOrderingToLinear(void);
private: private:
/// Private copy constructor to prevent accisdental copying /// Private copy constructor to prevent accisdental copying
Chunk(const Chunk& /*rhs*/) {}; Chunk(const Chunk& /*rhs*/) {};
@ -243,6 +246,11 @@ namespace PolyVox
private: private:
//Other current position information //Other current position information
VoxelType* mCurrentVoxel; VoxelType* mCurrentVoxel;
uint16_t m_uXPosInChunk;
uint16_t m_uYPosInChunk;
uint16_t m_uZPosInChunk;
uint16_t m_uChunkSideLengthMinusOne;
}; };
#endif #endif

View File

@ -21,6 +21,7 @@ freely, subject to the following restrictions:
distribution. distribution.
*******************************************************************************/ *******************************************************************************/
#include "PolyVox/Impl/Morton.h"
#include "PolyVox/Impl/Utility.h" #include "PolyVox/Impl/Utility.h"
namespace PolyVox namespace PolyVox
@ -36,6 +37,7 @@ namespace PolyVox
,m_v3dChunkSpacePosition(v3dPosition) ,m_v3dChunkSpacePosition(v3dPosition)
{ {
POLYVOX_ASSERT(m_pPager, "No valid pager supplied to chunk constructor."); POLYVOX_ASSERT(m_pPager, "No valid pager supplied to chunk constructor.");
POLYVOX_ASSERT(uSideLength <= 256, "Chunk side length cannot be greater than 256.");
// Compute the side length // Compute the side length
m_uSideLength = uSideLength; m_uSideLength = uSideLength;
@ -92,7 +94,7 @@ namespace PolyVox
} }
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Chunk::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const VoxelType PagedVolume<VoxelType>::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 // 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. // of uncompressed data. It's a performance critical code path so we use asserts rather than exceptions.
@ -101,12 +103,9 @@ namespace PolyVox
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the chunk"); 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."); POLYVOX_ASSERT(m_tData, "No uncompressed data - chunk must be decompressed before accessing voxels.");
return m_tData uint32_t index = morton256_x[uXPos] | morton256_y[uYPos] | morton256_z[uZPos];
[
uXPos + return m_tData[index];
uYPos * m_uSideLength +
uZPos * m_uSideLength * m_uSideLength
];
} }
template <typename VoxelType> template <typename VoxelType>
@ -116,7 +115,7 @@ namespace PolyVox
} }
template <typename VoxelType> template <typename VoxelType>
void PagedVolume<VoxelType>::Chunk::setVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue) void PagedVolume<VoxelType>::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 // 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. // of uncompressed data. It's a performance critical code path so we use asserts rather than exceptions.
@ -125,12 +124,9 @@ namespace PolyVox
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the chunk"); 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."); POLYVOX_ASSERT(m_tData, "No uncompressed data - chunk must be decompressed before accessing voxels.");
m_tData uint32_t index = morton256_x[uXPos] | morton256_y[uYPos] | morton256_z[uZPos];
[
uXPos + m_tData[index] = tValue;
uYPos * m_uSideLength +
uZPos * m_uSideLength * m_uSideLength
] = tValue;
this->m_bDataModified = true; this->m_bDataModified = true;
} }
@ -156,4 +152,54 @@ namespace PolyVox
uint32_t uSizeInBytes = uSideLength * uSideLength * uSideLength * sizeof(VoxelType); uint32_t uSizeInBytes = uSideLength * uSideLength * uSideLength * sizeof(VoxelType);
return uSizeInBytes; return uSizeInBytes;
} }
// This convienience function exists for historical reasons. Chunks used to store their data in 'linear' order but now we
// use Morton encoding. Users who still have data in linear order (on disk, in databases, etc) will need to call this function
// if they load the data in by memcpy()ing it via the raw pointer. On the other hand, if they set the data using setVoxel()
// then the ordering is automatically handled correctly.
template <typename VoxelType>
void PagedVolume<VoxelType>::Chunk::changeLinearOrderingToMorton(void)
{
VoxelType* pTempBuffer = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];
for (uint16_t z = 0; z < m_uSideLength; z++)
{
for (uint16_t y = 0; y < m_uSideLength; y++)
{
for (uint16_t x = 0; x < m_uSideLength; x++)
{
uint32_t uLinearIndex = x + y * m_uSideLength + z * m_uSideLength * m_uSideLength;
uint32_t uMortonIndex = morton256_x[x] | morton256_y[y] | morton256_z[z];
pTempBuffer[uMortonIndex] = m_tData[uLinearIndex];
}
}
}
std::memcpy(m_tData, pTempBuffer, getDataSizeInBytes());
delete[] pTempBuffer;
}
// Like the above function, this is provided fot easing backwards compatibility. In Cubiquity we have some
// old databases which use linear ordering, and we need to continue to save such data in linear order.
template <typename VoxelType>
void PagedVolume<VoxelType>::Chunk::changeMortonOrderingToLinear(void)
{
VoxelType* pTempBuffer = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];
for (uint16_t z = 0; z < m_uSideLength; z++)
{
for (uint16_t y = 0; y < m_uSideLength; y++)
{
for (uint16_t x = 0; x < m_uSideLength; x++)
{
uint32_t uLinearIndex = x + y * m_uSideLength + z * m_uSideLength * m_uSideLength;
uint32_t uMortonIndex = morton256_x[x] | morton256_y[y] | morton256_z[z];
pTempBuffer[uLinearIndex] = m_tData[uMortonIndex];
}
}
}
std::memcpy(m_tData, pTempBuffer, getDataSizeInBytes());
delete[] pTempBuffer;
}
} }

View File

@ -21,19 +21,35 @@ freely, subject to the following restrictions:
distribution. distribution.
*******************************************************************************/ *******************************************************************************/
#define CAN_GO_NEG_X(val) ((val % this->mVolume->m_uChunkSideLength != 0)) #include <array>
#define CAN_GO_POS_X(val) (((val + 1) % this->mVolume->m_uChunkSideLength != 0))
#define CAN_GO_NEG_Y(val) ((val % this->mVolume->m_uChunkSideLength != 0)) #define CAN_GO_NEG_X(val) (val > 0)
#define CAN_GO_POS_Y(val) (((val + 1) % this->mVolume->m_uChunkSideLength != 0)) #define CAN_GO_POS_X(val) (val < this->m_uChunkSideLengthMinusOne)
#define CAN_GO_NEG_Z(val) ((val % this->mVolume->m_uChunkSideLength != 0)) #define CAN_GO_NEG_Y(val) (val > 0)
#define CAN_GO_POS_Z(val) (((val + 1) % this->mVolume->m_uChunkSideLength != 0)) #define CAN_GO_POS_Y(val) (val < this->m_uChunkSideLengthMinusOne)
#define CAN_GO_NEG_Z(val) (val > 0)
#define CAN_GO_POS_Z(val) (val < this->m_uChunkSideLengthMinusOne)
#define NEG_X_DELTA (-(deltaX[this->m_uXPosInChunk-1]))
#define POS_X_DELTA (deltaX[this->m_uXPosInChunk])
#define NEG_Y_DELTA (-(deltaY[this->m_uYPosInChunk-1]))
#define POS_Y_DELTA (deltaY[this->m_uYPosInChunk])
#define NEG_Z_DELTA (-(deltaZ[this->m_uZPosInChunk-1]))
#define POS_Z_DELTA (deltaZ[this->m_uZPosInChunk])
namespace PolyVox namespace PolyVox
{ {
// These precomputed offset are used to determine how much we move our pointer by to move a single voxel in the x, y, or z direction given an x, y, or z starting position inside a chunk.
// More information in this discussion: https://bitbucket.org/volumesoffun/polyvox/issue/61/experiment-with-morton-ordering-of-voxel
static const std::array<int32_t, 256> deltaX = { 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 28087, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 224695, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 28087, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 1797559, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 28087, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 224695, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 28087, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1, 3511, 1, 7, 1, 55, 1, 7, 1, 439, 1, 7, 1, 55, 1, 7, 1 };
static const std::array<int32_t, 256> deltaY = { 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 56174, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 449390, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 56174, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 3595118, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 56174, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 449390, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 56174, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2, 7022, 2, 14, 2, 110, 2, 14, 2, 878, 2, 14, 2, 110, 2, 14, 2 };
static const std::array<int32_t, 256> deltaZ = { 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 112348, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 898780, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 112348, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 7190236, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 112348, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 898780, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 112348, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4, 14044, 4, 28, 4, 220, 4, 28, 4, 1756, 4, 28, 4, 220, 4, 28, 4 };
template <typename VoxelType> template <typename VoxelType>
PagedVolume<VoxelType>::Sampler::Sampler(PagedVolume<VoxelType>* volume) PagedVolume<VoxelType>::Sampler::Sampler(PagedVolume<VoxelType>* volume)
:BaseVolume<VoxelType>::template Sampler< PagedVolume<VoxelType> >(volume) :BaseVolume<VoxelType>::template Sampler< PagedVolume<VoxelType> >(volume)
{ {
this->m_uChunkSideLengthMinusOne = this->mVolume->m_uChunkSideLength - 1;
} }
template <typename VoxelType> template <typename VoxelType>
@ -102,13 +118,11 @@ namespace PolyVox
const int32_t uYChunk = this->mYPosInVolume >> this->mVolume->m_uChunkSideLengthPower; const int32_t uYChunk = this->mYPosInVolume >> this->mVolume->m_uChunkSideLengthPower;
const int32_t uZChunk = this->mZPosInVolume >> this->mVolume->m_uChunkSideLengthPower; const int32_t uZChunk = this->mZPosInVolume >> this->mVolume->m_uChunkSideLengthPower;
const uint16_t uXPosInChunk = static_cast<uint16_t>(this->mXPosInVolume - (uXChunk << this->mVolume->m_uChunkSideLengthPower)); m_uXPosInChunk = static_cast<uint16_t>(this->mXPosInVolume - (uXChunk << this->mVolume->m_uChunkSideLengthPower));
const uint16_t uYPosInChunk = static_cast<uint16_t>(this->mYPosInVolume - (uYChunk << this->mVolume->m_uChunkSideLengthPower)); m_uYPosInChunk = static_cast<uint16_t>(this->mYPosInVolume - (uYChunk << this->mVolume->m_uChunkSideLengthPower));
const uint16_t uZPosInChunk = static_cast<uint16_t>(this->mZPosInVolume - (uZChunk << this->mVolume->m_uChunkSideLengthPower)); m_uZPosInChunk = static_cast<uint16_t>(this->mZPosInVolume - (uZChunk << this->mVolume->m_uChunkSideLengthPower));
const uint32_t uVoxelIndexInChunk = uXPosInChunk + uint32_t uVoxelIndexInChunk = morton256_x[m_uXPosInChunk] | morton256_y[m_uYPosInChunk] | morton256_z[m_uZPosInChunk];
uYPosInChunk * this->mVolume->m_uChunkSideLength +
uZPosInChunk * this->mVolume->m_uChunkSideLength * this->mVolume->m_uChunkSideLength;
auto pCurrentChunk = this->mVolume->canReuseLastAccessedChunk(uXChunk, uYChunk, uZChunk) ? auto pCurrentChunk = this->mVolume->canReuseLastAccessedChunk(uXChunk, uYChunk, uZChunk) ?
this->mVolume->m_pLastAccessedChunk : this->mVolume->getChunk(uXChunk, uYChunk, uZChunk); this->mVolume->m_pLastAccessedChunk : this->mVolume->getChunk(uXChunk, uYChunk, uZChunk);
@ -134,7 +148,8 @@ namespace PolyVox
if(((this->mXPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) if(((this->mXPosInVolume) % this->mVolume->m_uChunkSideLength != 0))
{ {
//No need to compute new chunk. //No need to compute new chunk.
++mCurrentVoxel; mCurrentVoxel += POS_X_DELTA;
this->m_uXPosInChunk++;
} }
else else
{ {
@ -153,7 +168,8 @@ namespace PolyVox
if(((this->mYPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) if(((this->mYPosInVolume) % this->mVolume->m_uChunkSideLength != 0))
{ {
//No need to compute new chunk. //No need to compute new chunk.
mCurrentVoxel += this->mVolume->m_uChunkSideLength; mCurrentVoxel += POS_Y_DELTA;
this->m_uYPosInChunk++;
} }
else else
{ {
@ -172,7 +188,8 @@ namespace PolyVox
if(((this->mZPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) if(((this->mZPosInVolume) % this->mVolume->m_uChunkSideLength != 0))
{ {
//No need to compute new chunk. //No need to compute new chunk.
mCurrentVoxel += this->mVolume->m_uChunkSideLength * this->mVolume->m_uChunkSideLength; mCurrentVoxel += POS_Z_DELTA;
this->m_uZPosInChunk++;
} }
else else
{ {
@ -191,7 +208,8 @@ namespace PolyVox
if(((this->mXPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) if(((this->mXPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0))
{ {
//No need to compute new chunk. //No need to compute new chunk.
--mCurrentVoxel; mCurrentVoxel += NEG_X_DELTA;
this->m_uXPosInChunk--;
} }
else else
{ {
@ -210,7 +228,8 @@ namespace PolyVox
if(((this->mYPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) if(((this->mYPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0))
{ {
//No need to compute new chunk. //No need to compute new chunk.
mCurrentVoxel -= this->mVolume->m_uChunkSideLength; mCurrentVoxel += NEG_Y_DELTA;
this->m_uYPosInChunk--;
} }
else else
{ {
@ -229,7 +248,8 @@ namespace PolyVox
if(((this->mZPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) if(((this->mZPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0))
{ {
//No need to compute new chunk. //No need to compute new chunk.
mCurrentVoxel -= this->mVolume->m_uChunkSideLength * this->mVolume->m_uChunkSideLength; mCurrentVoxel += NEG_Z_DELTA;
this->m_uZPosInChunk--;
} }
else else
{ {
@ -241,9 +261,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_NEG_Y(this->m_uYPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + NEG_Y_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1);
} }
@ -251,9 +271,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_NEG_Y(this->m_uYPosInChunk))
{ {
return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + NEG_Y_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume);
} }
@ -261,9 +281,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_NEG_Y(this->m_uYPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + NEG_Y_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1);
} }
@ -271,9 +291,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1);
} }
@ -281,9 +301,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk))
{ {
return *(mCurrentVoxel - 1); return *(mCurrentVoxel + NEG_X_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume);
} }
@ -291,9 +311,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1);
} }
@ -301,9 +321,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_POS_Y(this->m_uYPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + POS_Y_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1);
} }
@ -311,9 +331,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_POS_Y(this->m_uYPosInChunk))
{ {
return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + POS_Y_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume);
} }
@ -321,9 +341,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const
{ {
if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_X(this->m_uXPosInChunk) && CAN_GO_POS_Y(this->m_uYPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_X_DELTA + POS_Y_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1);
} }
@ -333,9 +353,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const
{ {
if(CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_Y(this->m_uYPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_Y_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1);
} }
@ -343,9 +363,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const
{ {
if(CAN_GO_NEG_Y(this->mYPosInVolume) ) if (CAN_GO_NEG_Y(this->m_uYPosInChunk))
{ {
return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_Y_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume);
} }
@ -353,9 +373,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const
{ {
if(CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_Y(this->m_uYPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_Y_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1);
} }
@ -363,9 +383,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const
{ {
if(CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1);
} }
@ -379,9 +399,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const
{ {
if(CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1);
} }
@ -389,9 +409,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const
{ {
if(CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_POS_Y(this->m_uYPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_Y_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1);
} }
@ -399,9 +419,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const
{ {
if(CAN_GO_POS_Y(this->mYPosInVolume) ) if (CAN_GO_POS_Y(this->m_uYPosInChunk))
{ {
return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_Y_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume);
} }
@ -409,9 +429,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const
{ {
if(CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_POS_Y(this->m_uYPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_Y_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1);
} }
@ -421,9 +441,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_NEG_Y(this->m_uYPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + NEG_Y_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1);
} }
@ -431,9 +451,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_NEG_Y(this->m_uYPosInChunk))
{ {
return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + NEG_Y_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume);
} }
@ -441,9 +461,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_NEG_Y(this->m_uYPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + NEG_Y_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1);
} }
@ -451,9 +471,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1);
} }
@ -461,9 +481,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk))
{ {
return *(mCurrentVoxel + 1); return *(mCurrentVoxel + POS_X_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume);
} }
@ -471,9 +491,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1);
} }
@ -481,9 +501,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_POS_Y(this->m_uYPosInChunk) && CAN_GO_NEG_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + POS_Y_DELTA + NEG_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1);
} }
@ -491,9 +511,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_POS_Y(this->m_uYPosInChunk))
{ {
return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + POS_Y_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume);
} }
@ -501,9 +521,9 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const VoxelType PagedVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const
{ {
if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) if (CAN_GO_POS_X(this->m_uXPosInChunk) && CAN_GO_POS_Y(this->m_uYPosInChunk) && CAN_GO_POS_Z(this->m_uZPosInChunk))
{ {
return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); return *(mCurrentVoxel + POS_X_DELTA + POS_Y_DELTA + POS_Z_DELTA);
} }
return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1); return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1);
} }
@ -515,3 +535,10 @@ namespace PolyVox
#undef CAN_GO_POS_Y #undef CAN_GO_POS_Y
#undef CAN_GO_NEG_Z #undef CAN_GO_NEG_Z
#undef CAN_GO_POS_Z #undef CAN_GO_POS_Z
#undef NEG_X_DELTA
#undef POS_X_DELTA
#undef NEG_Y_DELTA
#undef POS_Y_DELTA
#undef NEG_Z_DELTA
#undef POS_Z_DELTA

View File

@ -83,56 +83,48 @@ int32_t testSamplersWithWrappingForwards(VolumeType* volume, Region region)
int32_t result = 0; int32_t result = 0;
//Test the sampler move functions //Test the sampler move functions
typename VolumeType::Sampler xSampler(volume); typename VolumeType::Sampler sampler(volume);
typename VolumeType::Sampler ySampler(volume);
typename VolumeType::Sampler zSampler(volume);
zSampler.setPosition(region.getLowerX(), region.getLowerY(), region.getLowerZ());
for (int z = region.getLowerZ(); z <= region.getUpperZ(); z++) for (int z = region.getLowerZ(); z <= region.getUpperZ(); z++)
{ {
ySampler = zSampler;
for (int y = region.getLowerY(); y <= region.getUpperY(); y++) for (int y = region.getLowerY(); y <= region.getUpperY(); y++)
{ {
xSampler = ySampler; sampler.setPosition(region.getLowerX(), y, z);
for (int x = region.getLowerX(); x <= region.getUpperX(); x++) for (int x = region.getLowerX(); x <= region.getUpperX(); x++)
{ {
xSampler.setPosition(x, y, z); // HACK - Accessing a volume through multiple samplers currently breaks the PagedVolume. result = cantorTupleFunction(result, sampler.peekVoxel1nx1ny1nz());
result = cantorTupleFunction(result, sampler.peekVoxel0px1ny1nz());
result = cantorTupleFunction(result, sampler.peekVoxel1px1ny1nz());
result = cantorTupleFunction(result, sampler.peekVoxel1nx0py1nz());
result = cantorTupleFunction(result, sampler.peekVoxel0px0py1nz());
result = cantorTupleFunction(result, sampler.peekVoxel1px0py1nz());
result = cantorTupleFunction(result, sampler.peekVoxel1nx1py1nz());
result = cantorTupleFunction(result, sampler.peekVoxel0px1py1nz());
result = cantorTupleFunction(result, sampler.peekVoxel1px1py1nz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx1ny1nz()); result = cantorTupleFunction(result, sampler.peekVoxel1nx1ny0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px1ny1nz()); result = cantorTupleFunction(result, sampler.peekVoxel0px1ny0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px1ny1nz()); result = cantorTupleFunction(result, sampler.peekVoxel1px1ny0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx0py1nz()); result = cantorTupleFunction(result, sampler.peekVoxel1nx0py0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px0py1nz()); result = cantorTupleFunction(result, sampler.peekVoxel0px0py0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px0py1nz()); result = cantorTupleFunction(result, sampler.peekVoxel1px0py0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx1py1nz()); result = cantorTupleFunction(result, sampler.peekVoxel1nx1py0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px1py1nz()); result = cantorTupleFunction(result, sampler.peekVoxel0px1py0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px1py1nz()); result = cantorTupleFunction(result, sampler.peekVoxel1px1py0pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx1ny0pz()); result = cantorTupleFunction(result, sampler.peekVoxel1nx1ny1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px1ny0pz()); result = cantorTupleFunction(result, sampler.peekVoxel0px1ny1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px1ny0pz()); result = cantorTupleFunction(result, sampler.peekVoxel1px1ny1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx0py0pz()); result = cantorTupleFunction(result, sampler.peekVoxel1nx0py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px0py0pz()); result = cantorTupleFunction(result, sampler.peekVoxel0px0py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px0py0pz()); result = cantorTupleFunction(result, sampler.peekVoxel1px0py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx1py0pz()); result = cantorTupleFunction(result, sampler.peekVoxel1nx1py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px1py0pz()); result = cantorTupleFunction(result, sampler.peekVoxel0px1py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px1py0pz()); result = cantorTupleFunction(result, sampler.peekVoxel1px1py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx1ny1pz()); sampler.movePositiveX();
result = cantorTupleFunction(result, xSampler.peekVoxel0px1ny1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px1ny1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx0py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px0py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px0py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1nx1py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px1py1pz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px1py1pz());
xSampler.movePositiveX();
} }
ySampler.movePositiveY();
} }
zSampler.movePositiveZ();
} }
return result; return result;
@ -181,20 +173,14 @@ int32_t testSamplersWithWrappingBackwards(VolumeType* volume, Region region)
//Test the sampler move functions //Test the sampler move functions
typename VolumeType::Sampler xSampler(volume); typename VolumeType::Sampler xSampler(volume);
typename VolumeType::Sampler ySampler(volume);
typename VolumeType::Sampler zSampler(volume);
zSampler.setPosition(region.getUpperX(), region.getUpperY(), region.getUpperZ());
for (int z = region.getUpperZ(); z >= region.getLowerZ(); z--) for (int z = region.getUpperZ(); z >= region.getLowerZ(); z--)
{ {
ySampler = zSampler;
for (int y = region.getUpperY(); y >= region.getLowerY(); y--) for (int y = region.getUpperY(); y >= region.getLowerY(); y--)
{ {
xSampler = ySampler; xSampler.setPosition(region.getUpperX(), y, z);
for (int x = region.getUpperX(); x >= region.getLowerX(); x--) for (int x = region.getUpperX(); x >= region.getLowerX(); x--)
{ {
xSampler.setPosition(x, y, z); // HACK - Accessing a volume through multiple samplers currently breaks the PagedVolume.
result = cantorTupleFunction(result, xSampler.peekVoxel1nx1ny1nz()); result = cantorTupleFunction(result, xSampler.peekVoxel1nx1ny1nz());
result = cantorTupleFunction(result, xSampler.peekVoxel0px1ny1nz()); result = cantorTupleFunction(result, xSampler.peekVoxel0px1ny1nz());
result = cantorTupleFunction(result, xSampler.peekVoxel1px1ny1nz()); result = cantorTupleFunction(result, xSampler.peekVoxel1px1ny1nz());
@ -227,9 +213,7 @@ int32_t testSamplersWithWrappingBackwards(VolumeType* volume, Region region)
xSampler.moveNegativeX(); xSampler.moveNegativeX();
} }
ySampler.moveNegativeY();
} }
zSampler.moveNegativeZ();
} }
return result; return result;