Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 namespace PolyVox
00025 {
00026 template <typename VoxelType>
00027 uint32_t VolumeChangeTracker<VoxelType>::m_uCurrentTime = 0;
00028
00030
00032 template <typename VoxelType>
00033 VolumeChangeTracker<VoxelType>::VolumeChangeTracker(LargeVolume<VoxelType>* volumeDataToSet, uint16_t regionSideLength)
00034 :m_bIsLocked(false)
00035 ,volumeData(0)
00036 ,m_uRegionSideLength(regionSideLength)
00037 {
00038 volumeData = volumeDataToSet;
00039 m_uVolumeWidthInRegions = volumeData->getWidth() / m_uRegionSideLength;
00040 m_uVolumeHeightInRegions = volumeData->getHeight() / m_uRegionSideLength;
00041 m_uVolumeDepthInRegions = volumeData->getDepth() / m_uRegionSideLength;
00042 m_uRegionSideLengthPower = PolyVox::logBase2(m_uRegionSideLength);
00043
00044 volRegionLastModified = new LargeVolume<int32_t>(m_uVolumeWidthInRegions, m_uVolumeHeightInRegions, m_uVolumeDepthInRegions, 0);
00045 }
00046
00047 template <typename VoxelType>
00048 VolumeChangeTracker<VoxelType>::~VolumeChangeTracker()
00049 {
00050 }
00051
00052 template <typename VoxelType>
00053 void VolumeChangeTracker<VoxelType>::setAllRegionsModified(void)
00054 {
00055 incrementCurrentTime();
00056 for(uint16_t blockZ = 0; blockZ < m_uVolumeDepthInRegions; ++blockZ)
00057 {
00058 for(uint16_t blockY = 0; blockY < m_uVolumeHeightInRegions; ++blockY)
00059 {
00060 for(uint16_t blockX = 0; blockX < m_uVolumeWidthInRegions; ++blockX)
00061 {
00062 volRegionLastModified->setVoxelAt(blockX, blockY, blockZ, m_uCurrentTime);
00063 }
00064 }
00065 }
00066 }
00067
00068 template <typename VoxelType>
00069 int32_t VolumeChangeTracker<VoxelType>::getCurrentTime(void) const
00070 {
00071 return m_uCurrentTime;
00072 }
00073
00074 template <typename VoxelType>
00075 int32_t VolumeChangeTracker<VoxelType>::getLastModifiedTimeForRegion(uint16_t uX, uint16_t uY, uint16_t uZ)
00076 {
00077 return volRegionLastModified->getVoxelAt(uX, uY, uZ);
00078 }
00079
00080 template <typename VoxelType>
00081 LargeVolume<VoxelType>* VolumeChangeTracker<VoxelType>::getWrappedVolume(void) const
00082 {
00083 return volumeData;
00084 }
00085
00086 template <typename VoxelType>
00087 void VolumeChangeTracker<VoxelType>::setVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value)
00088 {
00089
00090
00091
00092 incrementCurrentTime();
00093
00094 volumeData->setVoxelAt(x,y,z,value);
00095
00096
00097 if((x % m_uRegionSideLength != 0) &&
00098 (x % m_uRegionSideLength != m_uRegionSideLength-1) &&
00099 (y % m_uRegionSideLength != 0) &&
00100 (y % m_uRegionSideLength != m_uRegionSideLength-1) &&
00101 (z % m_uRegionSideLength != 0) &&
00102 (z % m_uRegionSideLength != m_uRegionSideLength-1))
00103 {
00104 volRegionLastModified->setVoxelAt(x >> m_uRegionSideLengthPower, y >> m_uRegionSideLengthPower, z >> m_uRegionSideLengthPower, m_uCurrentTime);
00105 }
00106 else
00107 {
00108 const uint16_t regionX = x >> m_uRegionSideLengthPower;
00109 const uint16_t regionY = y >> m_uRegionSideLengthPower;
00110 const uint16_t regionZ = z >> m_uRegionSideLengthPower;
00111
00112 const uint16_t minRegionX = (std::max)(uint16_t(0),uint16_t(regionX-1));
00113 const uint16_t minRegionY = (std::max)(uint16_t(0),uint16_t(regionY-1));
00114 const uint16_t minRegionZ = (std::max)(uint16_t(0),uint16_t(regionZ-1));
00115
00116 const uint16_t maxRegionX = (std::min)(uint16_t(m_uVolumeWidthInRegions-1),uint16_t(regionX+1));
00117 const uint16_t maxRegionY = (std::min)(uint16_t(m_uVolumeHeightInRegions-1),uint16_t(regionY+1));
00118 const uint16_t maxRegionZ = (std::min)(uint16_t(m_uVolumeDepthInRegions-1),uint16_t(regionZ+1));
00119
00120 for(uint16_t zCt = minRegionZ; zCt <= maxRegionZ; zCt++)
00121 {
00122 for(uint16_t yCt = minRegionY; yCt <= maxRegionY; yCt++)
00123 {
00124 for(uint16_t xCt = minRegionX; xCt <= maxRegionX; xCt++)
00125 {
00126 volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_uCurrentTime);
00127 }
00128 }
00129 }
00130 }
00131
00132
00133 incrementCurrentTime();
00134 }
00135
00136 template <typename VoxelType>
00137 void VolumeChangeTracker<VoxelType>::setLockedVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value)
00138 {
00139 assert(m_bIsLocked);
00140
00141
00142
00143
00144
00145 volumeData->setVoxelAt(x,y,z,value);
00146 }
00147
00148 template <typename VoxelType>
00149 void VolumeChangeTracker<VoxelType>::lockRegion(const Region& regToLock)
00150 {
00151 if(m_bIsLocked)
00152 {
00153 throw std::logic_error("A region is already locked. Please unlock it before locking another.");
00154 }
00155
00156 m_regLastLocked = regToLock;
00157 m_bIsLocked = true;
00158 }
00159
00160 template <typename VoxelType>
00161 void VolumeChangeTracker<VoxelType>::unlockRegion(void)
00162 {
00163 if(!m_bIsLocked)
00164 {
00165 throw std::logic_error("No region is locked. You must lock a region before you can unlock it.");
00166 }
00167
00168
00169
00170
00171 incrementCurrentTime();
00172
00173 const uint16_t firstRegionX = m_regLastLocked.getLowerCorner().getX() >> m_uRegionSideLengthPower;
00174 const uint16_t firstRegionY = m_regLastLocked.getLowerCorner().getY() >> m_uRegionSideLengthPower;
00175 const uint16_t firstRegionZ = m_regLastLocked.getLowerCorner().getZ() >> m_uRegionSideLengthPower;
00176
00177 const uint16_t lastRegionX = m_regLastLocked.getUpperCorner().getX() >> m_uRegionSideLengthPower;
00178 const uint16_t lastRegionY = m_regLastLocked.getUpperCorner().getY() >> m_uRegionSideLengthPower;
00179 const uint16_t lastRegionZ = m_regLastLocked.getUpperCorner().getZ() >> m_uRegionSideLengthPower;
00180
00181 for(uint16_t zCt = firstRegionZ; zCt <= lastRegionZ; zCt++)
00182 {
00183 for(uint16_t yCt = firstRegionY; yCt <= lastRegionY; yCt++)
00184 {
00185 for(uint16_t xCt = firstRegionX; xCt <= lastRegionX; xCt++)
00186 {
00187 volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_uCurrentTime);
00188 }
00189 }
00190 }
00191
00192 m_bIsLocked = false;
00193
00194
00195 incrementCurrentTime();
00196 }
00197
00198 template <typename VoxelType>
00199 void VolumeChangeTracker<VoxelType>::incrementCurrentTime(void)
00200 {
00201
00202 uint32_t time = m_uCurrentTime++;
00203
00204
00205
00206 assert(time < m_uCurrentTime);
00207 if(time >= m_uCurrentTime)
00208 {
00209 throw std::overflow_error("The VolumeChangeTracker time has overflowed.");
00210 }
00211 }
00212 }