PolyVox  0.2.1
Open source voxel management library
VolumeChangeTracker.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 {
26  template <typename VoxelType>
27  uint32_t VolumeChangeTracker<VoxelType>::m_uCurrentTime = 0;
28 
30  // VolumeChangeTracker
32  template <typename VoxelType>
34  :m_bIsLocked(false)
35  ,volumeData(0)
36  ,m_uRegionSideLength(regionSideLength)
37  {
38  volumeData = volumeDataToSet;
43 
45  }
46 
47  template <typename VoxelType>
49  {
50  }
51 
52  template <typename VoxelType>
54  {
55  incrementCurrentTime();
56  for(uint16_t blockZ = 0; blockZ < m_uVolumeDepthInRegions; ++blockZ)
57  {
58  for(uint16_t blockY = 0; blockY < m_uVolumeHeightInRegions; ++blockY)
59  {
60  for(uint16_t blockX = 0; blockX < m_uVolumeWidthInRegions; ++blockX)
61  {
62  volRegionLastModified->setVoxelAt(blockX, blockY, blockZ, m_uCurrentTime);
63  }
64  }
65  }
66  }
67 
68  template <typename VoxelType>
70  {
71  return m_uCurrentTime;
72  }
73 
74  template <typename VoxelType>
76  {
77  return volRegionLastModified->getVoxelAt(uX, uY, uZ);
78  }
79 
80  template <typename VoxelType>
82  {
83  return volumeData;
84  }
85 
86  template <typename VoxelType>
87  void VolumeChangeTracker<VoxelType>::setVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value)
88  {
89  //Note: We increase the time stamp both at the start and the end
90  //to avoid ambiguity about whether the timestamp comparison should
91  //be '<' vs '<=' or '>' vs '>=' in the users code.
92  incrementCurrentTime();
93 
94  volumeData->setVoxelAt(x,y,z,value);
95 
96  //If we are not on a boundary, just mark one region.
97  if((x % m_uRegionSideLength != 0) &&
98  (x % m_uRegionSideLength != m_uRegionSideLength-1) &&
99  (y % m_uRegionSideLength != 0) &&
100  (y % m_uRegionSideLength != m_uRegionSideLength-1) &&
101  (z % m_uRegionSideLength != 0) &&
102  (z % m_uRegionSideLength != m_uRegionSideLength-1))
103  {
104  volRegionLastModified->setVoxelAt(x >> m_uRegionSideLengthPower, y >> m_uRegionSideLengthPower, z >> m_uRegionSideLengthPower, m_uCurrentTime);
105  }
106  else //Mark surrounding regions as well
107  {
108  const uint16_t regionX = x >> m_uRegionSideLengthPower;
109  const uint16_t regionY = y >> m_uRegionSideLengthPower;
110  const uint16_t regionZ = z >> m_uRegionSideLengthPower;
111 
112  const uint16_t minRegionX = (std::max)(uint16_t(0),uint16_t(regionX-1));
113  const uint16_t minRegionY = (std::max)(uint16_t(0),uint16_t(regionY-1));
114  const uint16_t minRegionZ = (std::max)(uint16_t(0),uint16_t(regionZ-1));
115 
116  const uint16_t maxRegionX = (std::min)(uint16_t(m_uVolumeWidthInRegions-1),uint16_t(regionX+1));
117  const uint16_t maxRegionY = (std::min)(uint16_t(m_uVolumeHeightInRegions-1),uint16_t(regionY+1));
118  const uint16_t maxRegionZ = (std::min)(uint16_t(m_uVolumeDepthInRegions-1),uint16_t(regionZ+1));
119 
120  for(uint16_t zCt = minRegionZ; zCt <= maxRegionZ; zCt++)
121  {
122  for(uint16_t yCt = minRegionY; yCt <= maxRegionY; yCt++)
123  {
124  for(uint16_t xCt = minRegionX; xCt <= maxRegionX; xCt++)
125  {
126  volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_uCurrentTime);
127  }
128  }
129  }
130  }
131 
132  //Increment time stamp. See earlier note.
133  incrementCurrentTime();
134  }
135 
136  template <typename VoxelType>
137  void VolumeChangeTracker<VoxelType>::setLockedVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value)
138  {
139  assert(m_bIsLocked);
140 
141  //FIXME - rather than creating a iterator each time we should have one stored
142  /*Sampler<VoxelType> iterVol(*volumeData);
143  iterVol.setPosition(x,y,z);
144  iterVol.setVoxel(value);*/
145  volumeData->setVoxelAt(x,y,z,value);
146  }
147 
148  template <typename VoxelType>
150  {
151  if(m_bIsLocked)
152  {
153  throw std::logic_error("A region is already locked. Please unlock it before locking another.");
154  }
155 
156  m_regLastLocked = regToLock;
157  m_bIsLocked = true;
158  }
159 
160  template <typename VoxelType>
162  {
163  if(!m_bIsLocked)
164  {
165  throw std::logic_error("No region is locked. You must lock a region before you can unlock it.");
166  }
167 
168  //Note: We increase the time stamp both at the start and the end
169  //to avoid ambiguity about whether the timestamp comparison should
170  //be '<' vs '<=' or '>' vs '>=' in the users code.
171  incrementCurrentTime();
172 
173  const uint16_t firstRegionX = m_regLastLocked.getLowerCorner().getX() >> m_uRegionSideLengthPower;
174  const uint16_t firstRegionY = m_regLastLocked.getLowerCorner().getY() >> m_uRegionSideLengthPower;
175  const uint16_t firstRegionZ = m_regLastLocked.getLowerCorner().getZ() >> m_uRegionSideLengthPower;
176 
177  const uint16_t lastRegionX = m_regLastLocked.getUpperCorner().getX() >> m_uRegionSideLengthPower;
178  const uint16_t lastRegionY = m_regLastLocked.getUpperCorner().getY() >> m_uRegionSideLengthPower;
179  const uint16_t lastRegionZ = m_regLastLocked.getUpperCorner().getZ() >> m_uRegionSideLengthPower;
180 
181  for(uint16_t zCt = firstRegionZ; zCt <= lastRegionZ; zCt++)
182  {
183  for(uint16_t yCt = firstRegionY; yCt <= lastRegionY; yCt++)
184  {
185  for(uint16_t xCt = firstRegionX; xCt <= lastRegionX; xCt++)
186  {
187  volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_uCurrentTime);
188  }
189  }
190  }
191 
192  m_bIsLocked = false;
193 
194  //Increment time stamp. See earlier note.
195  incrementCurrentTime();
196  }
197 
198  template <typename VoxelType>
200  {
201  //Increment the current time.
202  uint32_t time = m_uCurrentTime++;
203 
204  //Watch out for wraparound. Hopefully this will never happen
205  //as we have a pretty big counter, but it's best to be sure...
206  assert(time < m_uCurrentTime);
207  if(time >= m_uCurrentTime)
208  {
209  throw std::overflow_error("The VolumeChangeTracker time has overflowed.");
210  }
211  }
212 }