PolyVox  0.2.1
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  m_uNoOfVoxelsPerBlock = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength;
213 
214  //m_regValidRegionInBlocks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uBlockSideLengthPower);
215  //m_regValidRegionInBlocks.setLowerY(this->m_regValidRegion.getLowerY() >> m_uBlockSideLengthPower);
216  //m_regValidRegionInBlocks.setLowerZ(this->m_regValidRegion.getLowerZ() >> m_uBlockSideLengthPower);
217  m_regValidRegionInBlocks.setLowerCorner(Vector3DInt32(this->m_regValidRegion.getLowerCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getZ() >> m_uBlockSideLengthPower));
218  //m_regValidRegionInBlocks.setUpperX(this->m_regValidRegion.getUpperX() >> m_uBlockSideLengthPower);
219  //m_regValidRegionInBlocks.setUpperY(this->m_regValidRegion.getUpperY() >> m_uBlockSideLengthPower);
220  //m_regValidRegionInBlocks.setUpperZ(this->m_regValidRegion.getUpperZ() >> m_uBlockSideLengthPower);
221  m_regValidRegionInBlocks.setUpperCorner(Vector3DInt32(this->m_regValidRegion.getUpperCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getZ() >> m_uBlockSideLengthPower));
222 
223  //Compute the size of the volume in blocks (and note +1 at the end)
224  m_uWidthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getX() - m_regValidRegionInBlocks.getLowerCorner().getX() + 1;
225  m_uHeightInBlocks = m_regValidRegionInBlocks.getUpperCorner().getY() - m_regValidRegionInBlocks.getLowerCorner().getY() + 1;
226  m_uDepthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getZ() - m_regValidRegionInBlocks.getLowerCorner().getZ() + 1;
227  m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
228 
229  //Allocate the data
230  m_pBlocks = new Block[m_uNoOfBlocksInVolume];
231  for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
232  {
233  m_pBlocks[i].initialise(m_uBlockSideLength);
234  }
235 
236  //Create the border block
237  m_pUncompressedBorderData = new VoxelType[m_uNoOfVoxelsPerBlock];
238  std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, VoxelType());
239 
240  //Other properties we might find useful later
241  this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
242  this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
243  this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
244  }
245 
246  template <typename VoxelType>
247  typename SimpleVolume<VoxelType>::Block* SimpleVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
248  {
249  //The lower left corner of the volume could be
250  //anywhere, but array indices need to start at zero.
251  uBlockX -= m_regValidRegionInBlocks.getLowerCorner().getX();
252  uBlockY -= m_regValidRegionInBlocks.getLowerCorner().getY();
253  uBlockZ -= m_regValidRegionInBlocks.getLowerCorner().getZ();
254 
255  //Compute the block index
256  uint32_t uBlockIndex =
257  uBlockX +
258  uBlockY * m_uWidthInBlocks +
259  uBlockZ * m_uWidthInBlocks * m_uHeightInBlocks;
260 
261  //Return the block
262  return &(m_pBlocks[uBlockIndex]);
263  }
264 
270  template <typename VoxelType>
272  {
273  uint32_t uSizeInBytes = sizeof(SimpleVolume);
274 
275  uint32_t uSizeOfBlockInBytes = m_uNoOfVoxelsPerBlock * sizeof(VoxelType);
276 
277  //Memory used by the blocks ( + 1 is for border)
278  uSizeInBytes += uSizeOfBlockInBytes * (m_uNoOfBlocksInVolume + 1);
279 
280  return uSizeInBytes;
281  }
282 
283 }
284