PolyVox  0.3.0-dev
Open source voxel management library
LargeVolume.h
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 #ifndef __PolyVox_LargeVolume_H__
25 #define __PolyVox_LargeVolume_H__
26 
27 #include "PolyVoxCore/BaseVolume.h"
28 #include "Impl/Block.h"
29 #include "PolyVoxCore/Compressor.h"
30 #include "PolyVoxCore/Log.h"
31 #include "PolyVoxCore/Region.h"
32 #include "PolyVoxCore/Vector.h"
33 
34 #include <limits>
35 #include <cstdlib> //For abort()
36 #include <cstring> //For memcpy
37 #include <list>
38 #include <map>
39 #include <memory>
40 #include <stdexcept> //For invalid_argument
41 #include <vector>
42 
43 namespace PolyVox
44 {
45  template <typename VoxelType> class ConstVolumeProxy;
46 
158  template <typename VoxelType>
159  class LargeVolume : public BaseVolume<VoxelType>
160  {
161  public:
162  //There seems to be some descrepency between Visual Studio and GCC about how the following class should be declared.
163  //There is a work around (see also See http://goo.gl/qu1wn) given below which appears to work on VS2010 and GCC, but
164  //which seems to cause internal compiler errors on VS2008 when building with the /Gm 'Enable Minimal Rebuild' compiler
165  //option. For now it seems best to 'fix' it with the preprocessor insstead, but maybe the workaround can be reinstated
166  //in the future
167  //typedef Volume<VoxelType> VolumeOfVoxelType; //Workaround for GCC/VS2010 differences.
168  //class Sampler : public VolumeOfVoxelType::template Sampler< LargeVolume<VoxelType> >
169  #ifndef SWIG
170 #if defined(_MSC_VER)
171  class Sampler : public BaseVolume<VoxelType>::Sampler< LargeVolume<VoxelType> > //This line works on VS2010
172 #else
173  class Sampler : public BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> > //This line works on GCC
174 #endif
175  {
176  public:
178  ~Sampler();
179 
182  inline VoxelType getVoxel(void) const;
183 
184  void setPosition(const Vector3DInt32& v3dNewPos);
185  void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
186  inline bool setVoxel(VoxelType tValue);
187 
188  void movePositiveX(void);
189  void movePositiveY(void);
190  void movePositiveZ(void);
191 
192  void moveNegativeX(void);
193  void moveNegativeY(void);
194  void moveNegativeZ(void);
195 
196  inline VoxelType peekVoxel1nx1ny1nz(void) const;
197  inline VoxelType peekVoxel1nx1ny0pz(void) const;
198  inline VoxelType peekVoxel1nx1ny1pz(void) const;
199  inline VoxelType peekVoxel1nx0py1nz(void) const;
200  inline VoxelType peekVoxel1nx0py0pz(void) const;
201  inline VoxelType peekVoxel1nx0py1pz(void) const;
202  inline VoxelType peekVoxel1nx1py1nz(void) const;
203  inline VoxelType peekVoxel1nx1py0pz(void) const;
204  inline VoxelType peekVoxel1nx1py1pz(void) const;
205 
206  inline VoxelType peekVoxel0px1ny1nz(void) const;
207  inline VoxelType peekVoxel0px1ny0pz(void) const;
208  inline VoxelType peekVoxel0px1ny1pz(void) const;
209  inline VoxelType peekVoxel0px0py1nz(void) const;
210  inline VoxelType peekVoxel0px0py0pz(void) const;
211  inline VoxelType peekVoxel0px0py1pz(void) const;
212  inline VoxelType peekVoxel0px1py1nz(void) const;
213  inline VoxelType peekVoxel0px1py0pz(void) const;
214  inline VoxelType peekVoxel0px1py1pz(void) const;
215 
216  inline VoxelType peekVoxel1px1ny1nz(void) const;
217  inline VoxelType peekVoxel1px1ny0pz(void) const;
218  inline VoxelType peekVoxel1px1ny1pz(void) const;
219  inline VoxelType peekVoxel1px0py1nz(void) const;
220  inline VoxelType peekVoxel1px0py0pz(void) const;
221  inline VoxelType peekVoxel1px0py1pz(void) const;
222  inline VoxelType peekVoxel1px1py1nz(void) const;
223  inline VoxelType peekVoxel1px1py0pz(void) const;
224  inline VoxelType peekVoxel1px1py1pz(void) const;
225 
226  private:
227  //Other current position information
228  VoxelType* mCurrentVoxel;
229  };
230 
231  // Make the ConstVolumeProxy a friend
233 
234  struct LoadedBlock
235  {
236  public:
237  LoadedBlock(uint16_t uSideLength = 0)
238  :block(uSideLength)
239  ,timestamp(0)
240  {
241  }
242 
245  };
246  #endif
247 
248  public:
251  (
252  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
253  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
254  uint16_t uBlockSideLength = 32
255  );
258  (
259  const Region& regValid,
260  Compressor* pCompressor = 0,
261  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler = 0,
262  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler = 0,
263  bool bPagingEnabled = false,
264  uint16_t uBlockSideLength = 32
265  );
267  ~LargeVolume();
268 
270  VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
272  VoxelType getVoxel(const Vector3DInt32& v3dPos) const;
274  VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
276  VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
278  VoxelType getVoxelWithWrapping(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType()) const;
280  VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType()) const;
281 
283  void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks);
285  void setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory);
287  bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
289  bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
291  void prefetch(Region regPrefetch);
293  void flush(Region regFlush);
295  void flushAll();
296 
298  void clearBlockCache(void);
300  float calculateCompressionRatio(void);
303 
304  protected:
306  LargeVolume(const LargeVolume& rhs);
307 
309  LargeVolume& operator=(const LargeVolume& rhs);
310 
311  private:
312 
313  struct BlockPositionCompare
314  {
315  bool operator() (const PolyVox::Vector3DInt32& a, const PolyVox::Vector3DInt32& b) const
316  {
317  const uint32_t size = 3;
318  for(uint32_t ct = 0; ct < size; ++ct)
319  {
320  if (a.getElement(ct) < b.getElement(ct))
321  return true;
322  if (b.getElement(ct) < a.getElement(ct))
323  return false;
324  }
325  return false;
326  }
327  };
328  void initialise(const Region& regValidRegion, uint16_t uBlockSideLength);
329 
333  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataRequiredHandler;
338  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataOverflowHandler;
339 
340  Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
341  void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock) const;
343  bool setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const;
344 
345  //The block data
346  mutable std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare> m_pBlocks;
347 
348  //The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
349  //than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
350  //of blocks. However, this could mean the same block data is uncompressed and modified in more than one
351  //location in memory... could be messy with threading.
352  mutable std::vector< LoadedBlock* > m_vecUncompressedBlockCache;
353  mutable uint32_t m_uTimestamper;
354  mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
355  mutable Block<VoxelType>* m_pLastAccessedBlock;
356  uint32_t m_uMaxNumberOfUncompressedBlocks;
357  uint32_t m_uMaxNumberOfBlocksInMemory;
358 
359  //The size of the volume
360  Region m_regValidRegionInBlocks;
361 
362  //The size of the blocks
363  uint16_t m_uBlockSideLength;
364  uint8_t m_uBlockSideLengthPower;
365 
366  //The compressor used by the Blocks to compress their data if required.
367  Compressor* m_pCompressor;
368 
369  bool m_bPagingEnabled;
370  };
371 }
372 
375 
376 #endif //__PolyVox_LargeVolume_H__