PolyVox  0.2.0
Open source voxel management library
SimpleVolume.inl
Go to the documentation of this file.
1 /*******************************************************************************
2 Copyright (c) 2005-2009 David Williams
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12  1. The origin of this software must not be misrepresented; you must not
13  claim that you wrote the original software. If you use this software
14  in a product, an acknowledgment in the product documentation would be
15  appreciated but is not required.
16 
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19 
20  3. This notice may not be removed or altered from any source
21  distribution.
22 *******************************************************************************/
23 
24 namespace PolyVox
25 {
31  template <typename VoxelType>
32  SimpleVolume<VoxelType>::SimpleVolume(const Region& regValid, uint16_t uBlockSideLength)
33  :BaseVolume<VoxelType>(regValid)
34  {
35  //Create a volume of the right size.
36  initialise(regValid,uBlockSideLength);
37  }
38 
46  template <typename VoxelType>
48  {
49  assert(false); // See function comment above.
50  }
51 
55  template <typename VoxelType>
57  {
58  delete[] m_pBlocks;
59  delete[] m_pUncompressedBorderData;
60  }
61 
69  template <typename VoxelType>
71  {
72  assert(false); // See function comment above.
73  }
74 
80  template <typename VoxelType>
82  {
83  return *m_pUncompressedBorderData;
84  }
85 
92  template <typename VoxelType>
93  VoxelType SimpleVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
94  {
95  if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
96  {
97  const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
98  const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
99  const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
100 
101  const uint16_t xOffset = static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
102  const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
103  const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
104 
105  typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
106 
107  return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
108  }
109  else
110  {
111  return getBorderValue();
112  }
113  }
114 
119  template <typename VoxelType>
120  VoxelType SimpleVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
121  {
122  return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
123  }
124 
128  template <typename VoxelType>
129  void SimpleVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
130  {
131  /*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
132  return pUncompressedBorderBlock->fill(tBorder);*/
133  std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, tBorder);
134  }
135 
143  template <typename VoxelType>
144  bool SimpleVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
145  {
146  assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
147 
148  const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
149  const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
150  const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
151 
152  const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
153  const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
154  const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
155 
156  typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
157 
158  pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
159 
160  //Return true to indicate that we modified a voxel.
161  return true;
162  }
163 
169  template <typename VoxelType>
170  bool SimpleVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
171  {
172  return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
173  }
174 
178  template <typename VoxelType>
179  void SimpleVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength)
180  {
181  //Debug mode validation
182  assert(uBlockSideLength >= 8);
183  assert(uBlockSideLength <= 256);
184  assert(isPowerOf2(uBlockSideLength));
185 
186  //Release mode validation
187  if(uBlockSideLength < 8)
188  {
189  throw std::invalid_argument("Block side length should be at least 8");
190  }
191  if(uBlockSideLength > 256)
192  {
193  throw std::invalid_argument("Block side length should not be more than 256");
194  }
195  if(!isPowerOf2(uBlockSideLength))
196  {
197  throw std::invalid_argument("Block side length must be a power of two.");
198  }
199 
200  m_uBlockSideLength = uBlockSideLength;
201  m_uNoOfVoxelsPerBlock = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength;
202  m_pUncompressedBorderData = 0;
203 
204  this->m_regValidRegion = regValidRegion;
205 
206  m_regValidRegionInBlocks.setLowerCorner(this->m_regValidRegion.getLowerCorner() / static_cast<int32_t>(uBlockSideLength));
207  m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner() / static_cast<int32_t>(uBlockSideLength));
208 
209  //Compute the block side length
210  m_uBlockSideLength = uBlockSideLength;
211  m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
212 
213  //Compute the size of the volume in blocks (and note +1 at the end)
214  m_uWidthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getX() - m_regValidRegionInBlocks.getLowerCorner().getX() + 1;
215  m_uHeightInBlocks = m_regValidRegionInBlocks.getUpperCorner().getY() - m_regValidRegionInBlocks.getLowerCorner().getY() + 1;
216  m_uDepthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getZ() - m_regValidRegionInBlocks.getLowerCorner().getZ() + 1;
217  m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
218 
219  //Allocate the data
220  m_pBlocks = new Block[m_uNoOfBlocksInVolume];
221  for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
222  {
223  m_pBlocks[i].initialise(m_uBlockSideLength);
224  }
225 
226  //Create the border block
227  m_pUncompressedBorderData = new VoxelType[m_uNoOfVoxelsPerBlock];
228  std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, VoxelType());
229 
230  //Other properties we might find useful later
231  this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
232  this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
233  this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
234  }
235 
236  template <typename VoxelType>
237  typename SimpleVolume<VoxelType>::Block* SimpleVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
238  {
239  //The lower left corner of the volume could be
240  //anywhere, but array indices need to start at zero.
241  uBlockX -= m_regValidRegionInBlocks.getLowerCorner().getX();
242  uBlockY -= m_regValidRegionInBlocks.getLowerCorner().getY();
243  uBlockZ -= m_regValidRegionInBlocks.getLowerCorner().getZ();
244 
245  //Compute the block index
246  uint32_t uBlockIndex =
247  uBlockX +
248  uBlockY * m_uWidthInBlocks +
249  uBlockZ * m_uWidthInBlocks * m_uHeightInBlocks;
250 
251  //Return the block
252  return &(m_pBlocks[uBlockIndex]);
253  }
254 
260  template <typename VoxelType>
262  {
263  uint32_t uSizeInBytes = sizeof(SimpleVolume);
264 
265  uint32_t uSizeOfBlockInBytes = m_uNoOfVoxelsPerBlock * sizeof(VoxelType);
266 
267  //Memory used by the blocks ( + 1 is for border)
268  uSizeInBytes += uSizeOfBlockInBytes * (m_uNoOfBlocksInVolume + 1);
269 
270  return uSizeInBytes;
271  }
272 
273 }
274