PolyVox  0.2.1
Open source voxel management library
LowPassFilter.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 {
33  template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
34  LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::LowPassFilter(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst, uint32_t uKernelSize)
35  :m_pVolSrc(pVolSrc)
36  ,m_regSrc(regSrc)
37  ,m_pVolDst(pVolDst)
38  ,m_regDst(regDst)
39  ,m_uKernelSize(uKernelSize)
40  {
41  //Kernel size must be at least three
42  assert(m_uKernelSize >= 3);
43  m_uKernelSize = std::max(m_uKernelSize, static_cast<uint32_t>(3)); //For release builds
44 
45  //Kernel size must be odd
46  assert(m_uKernelSize % 2 == 1);
47  if(m_uKernelSize % 2 == 0) //For release builds
48  {
49  m_uKernelSize++;
50  }
51  }
52 
53  template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
55  {
56  int32_t iSrcMinX = m_regSrc.getLowerCorner().getX();
57  int32_t iSrcMinY = m_regSrc.getLowerCorner().getY();
58  int32_t iSrcMinZ = m_regSrc.getLowerCorner().getZ();
59 
60  int32_t iSrcMaxX = m_regSrc.getUpperCorner().getX();
61  int32_t iSrcMaxY = m_regSrc.getUpperCorner().getY();
62  int32_t iSrcMaxZ = m_regSrc.getUpperCorner().getZ();
63 
64  int32_t iDstMinX = m_regDst.getLowerCorner().getX();
65  int32_t iDstMinY = m_regDst.getLowerCorner().getY();
66  int32_t iDstMinZ = m_regDst.getLowerCorner().getZ();
67 
68  //int32_t iDstMaxX = m_regDst.getUpperCorner().getX();
69  //int32_t iDstMaxY = m_regDst.getUpperCorner().getY();
70  //int32_t iDstMaxZ = m_regDst.getUpperCorner().getZ();
71 
72  typename SrcVolumeType::Sampler srcSampler(m_pVolSrc);
73 
74  for(int32_t iSrcZ = iSrcMinZ, iDstZ = iDstMinZ; iSrcZ <= iSrcMaxZ; iSrcZ++, iDstZ++)
75  {
76  for(int32_t iSrcY = iSrcMinY, iDstY = iDstMinY; iSrcY <= iSrcMaxY; iSrcY++, iDstY++)
77  {
78  for(int32_t iSrcX = iSrcMinX, iDstX = iDstMinX; iSrcX <= iSrcMaxX; iSrcX++, iDstX++)
79  {
80  AccumulationType tSrcVoxel(0);
81  srcSampler.setPosition(iSrcX, iSrcY, iSrcZ);
82 
83  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1nz());
84  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny0pz());
85  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1pz());
86  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1nz());
87  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py0pz());
88  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1pz());
89  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1nz());
90  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py0pz());
91  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1pz());
92 
93  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1nz());
94  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny0pz());
95  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1pz());
96  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1nz());
97  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py0pz());
98  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1pz());
99  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1nz());
100  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py0pz());
101  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1pz());
102 
103  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1nz());
104  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny0pz());
105  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1pz());
106  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1nz());
107  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py0pz());
108  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1pz());
109  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1nz());
110  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py0pz());
111  tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1pz());
112 
113  tSrcVoxel /= 27;
114 
115  //tSrcVoxel.setDensity(uDensity);
116  m_pVolDst->setVoxelAt(iSrcX, iSrcY, iSrcZ, static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel));
117  }
118  }
119  }
120  }
121 
122  template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
124  {
125  const uint32_t border = (m_uKernelSize - 1) / 2;
126 
127  Vector3DInt32 satLowerCorner = m_regSrc.getLowerCorner() - Vector3DInt32(border, border, border);
128  Vector3DInt32 satUpperCorner = m_regSrc.getUpperCorner() + Vector3DInt32(border, border, border);
129 
130  //Use floats for the SAT volume to ensure it works with negative
131  //densities and with both integral and floating point input volumes.
132  RawVolume<AccumulationType> satVolume(Region(satLowerCorner, satUpperCorner));
133 
134  //Clear to zeros (necessary?)
135  //FIXME - use Volume::fill() method. Implemented in base class as below
136  //but with optimised implementations in subclasses?
137  for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
138  {
139  for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
140  {
141  for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
142  {
143  satVolume.setVoxelAt(x,y,z,0);
144  }
145  }
146  }
147 
148  typename RawVolume<AccumulationType>::Sampler satVolumeIter(&satVolume);
149 
151  satIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
152  satIterCont.m_Iter = &satVolumeIter;
153  satIterCont.reset();
154 
155  typename SrcVolumeType::Sampler srcVolumeIter(m_pVolSrc);
156 
158  srcIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
159  srcIterCont.m_Iter = &srcVolumeIter;
160  srcIterCont.reset();
161 
162  do
163  {
164  AccumulationType previousSum = static_cast<AccumulationType>(satVolumeIter.peekVoxel1nx0py0pz());
165  AccumulationType currentVal = static_cast<AccumulationType>(srcVolumeIter.getVoxel());
166 
167  satVolumeIter.setVoxel(previousSum + currentVal);
168 
169  srcIterCont.moveForward();
170 
171  }while(satIterCont.moveForward());
172 
173  //Build SAT in three passes
174  /*for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
175  {
176  for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
177  {
178  for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
179  {
180  AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x-1,y,z));
181  AccumulationType currentVal = static_cast<AccumulationType>(m_pVolSrc->getVoxelAt(x,y,z));
182 
183  satVolume.setVoxelAt(x,y,z,previousSum + currentVal);
184  }
185  }
186  }*/
187 
188  for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
189  {
190  for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
191  {
192  for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
193  {
194  AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y-1,z));
195  AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z));
196 
197  satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
198  }
199  }
200  }
201 
202  for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
203  {
204  for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
205  {
206  for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
207  {
208  AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z-1));
209  AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z));
210 
211  satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
212  }
213  }
214  }
215 
216  //Now compute the average
217  const Vector3DInt32& v3dDstLowerCorner = m_regDst.getLowerCorner();
218  const Vector3DInt32& v3dDstUpperCorner = m_regDst.getUpperCorner();
219 
220  const Vector3DInt32& v3dSrcLowerCorner = m_regSrc.getLowerCorner();
221 
222  for(int32_t iDstZ = v3dDstLowerCorner.getZ(), iSrcZ = v3dSrcLowerCorner.getZ(); iDstZ <= v3dDstUpperCorner.getZ(); iDstZ++, iSrcZ++)
223  {
224  for(int32_t iDstY = v3dDstLowerCorner.getY(), iSrcY = v3dSrcLowerCorner.getY(); iDstY <= v3dDstUpperCorner.getY(); iDstY++, iSrcY++)
225  {
226  for(int32_t iDstX = v3dDstLowerCorner.getX(), iSrcX = v3dSrcLowerCorner.getX(); iDstX <= v3dDstUpperCorner.getX(); iDstX++, iSrcX++)
227  {
228  int32_t satLowerX = iSrcX - border - 1;
229  int32_t satLowerY = iSrcY - border - 1;
230  int32_t satLowerZ = iSrcZ - border - 1;
231 
232  int32_t satUpperX = iSrcX + border;
233  int32_t satUpperY = iSrcY + border;
234  int32_t satUpperZ = iSrcZ + border;
235 
236  AccumulationType a = satVolume.getVoxelAt(satLowerX,satLowerY,satLowerZ);
237  AccumulationType b = satVolume.getVoxelAt(satUpperX,satLowerY,satLowerZ);
238  AccumulationType c = satVolume.getVoxelAt(satLowerX,satUpperY,satLowerZ);
239  AccumulationType d = satVolume.getVoxelAt(satUpperX,satUpperY,satLowerZ);
240  AccumulationType e = satVolume.getVoxelAt(satLowerX,satLowerY,satUpperZ);
241  AccumulationType f = satVolume.getVoxelAt(satUpperX,satLowerY,satUpperZ);
242  AccumulationType g = satVolume.getVoxelAt(satLowerX,satUpperY,satUpperZ);
243  AccumulationType h = satVolume.getVoxelAt(satUpperX,satUpperY,satUpperZ);
244 
245  AccumulationType sum = h+c-d-g-f-a+b+e;
246  uint32_t sideLength = border * 2 + 1;
247  AccumulationType average = sum / (sideLength*sideLength*sideLength);
248 
249  m_pVolDst->setVoxelAt(iDstX, iDstY, iDstZ, static_cast<typename DstVolumeType::VoxelType>(average));
250  }
251  }
252  }
253  }
254 }