PolyVox  0.2.1
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/Log.h"
30 #include "PolyVoxCore/Region.h"
31 #include "PolyVoxCore/Vector.h"
32 
33 #include <limits>
34 #include <cassert>
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 #if defined(_MSC_VER)
170  class Sampler : public BaseVolume<VoxelType>::Sampler< LargeVolume<VoxelType> > //This line works on VS2010
171 #else
172  class Sampler : public BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> > //This line works on GCC
173 #endif
174  {
175  public:
177  ~Sampler();
178 
179  Sampler& operator=(const Sampler& rhs);
180 
181  VoxelType getSubSampledVoxel(uint8_t uLevel) const;
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 
244  uint32_t timestamp;
245  };
246 
247  public:
250  (
251  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
252  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
253  uint16_t uBlockSideLength = 32
254  );
257  (
258  const Region& regValid,
259  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler = 0,
260  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler = 0,
261  bool bPagingEnabled = false,
262  uint16_t uBlockSideLength = 32
263  );
265  ~LargeVolume();
266 
268  VoxelType getBorderValue(void) const;
270  VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
272  VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
273 
274  //Sets whether or not blocks are compressed in memory
275  void setCompressionEnabled(bool bCompressionEnabled);
277  void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks);
279  void setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory);
281  void setBorderValue(const VoxelType& tBorder);
283  bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
285  bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
287  void prefetch(Region regPrefetch);
289  void flush(Region regFlush);
291  void flushAll();
292 
294  void clearBlockCache(void);
296  float calculateCompressionRatio(void);
298  uint32_t calculateSizeInBytes(void);
299 
300  protected:
302  LargeVolume(const LargeVolume& rhs);
303 
305  LargeVolume& operator=(const LargeVolume& rhs);
306 
307  private:
308  void initialise(const Region& regValidRegion, uint16_t uBlockSideLength);
309 
313  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataRequiredHandler;
318  polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataOverflowHandler;
319 
320  Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
321  void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const;
323  bool setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const;
324 
325  //The block data
326  mutable std::map<Vector3DInt32, LoadedBlock > m_pBlocks;
327 
328  //The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
329  //than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
330  //of blocks. However, this could mean the same block data is uncompressed and modified in more than one
331  //location in memory... could be messy with threading.
332  mutable std::vector< LoadedBlock* > m_vecUncompressedBlockCache;
333  mutable uint32_t m_uTimestamper;
334  mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
335  mutable Block<VoxelType>* m_pLastAccessedBlock;
336  uint32_t m_uMaxNumberOfUncompressedBlocks;
337  uint32_t m_uMaxNumberOfBlocksInMemory;
338 
339  //We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
340  //block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a
341  //good chance we'll often hit it anyway. It's a chunk of homogenous data (rather than a single value) so that
342  //the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume.
343  VoxelType* m_pUncompressedBorderData;
344 
345  //The size of the volume
346  Region m_regValidRegionInBlocks;
347 
348  //The size of the blocks
349  uint16_t m_uBlockSideLength;
350  uint8_t m_uBlockSideLengthPower;
351 
352  bool m_bCompressionEnabled;
353  bool m_bPagingEnabled;
354  };
355 }
356 
359 
360 #endif //__PolyVox_LargeVolume_H__