00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef __VCG_TRIVIAL_WALKER
00024 #define __VCG_TRIVIAL_WALKER
00025
00026 namespace vcg {
00027
00028
00029
00030
00031 template <class VOX_TYPE>
00032 class SimpleVolume : public BasicGrid<typename VOX_TYPE::ScalarType>
00033 {
00034 public:
00035 typedef VOX_TYPE VoxelType;
00036 typedef typename VoxelType::ScalarType ScalarType;
00037 typedef typename BasicGrid<typename VOX_TYPE::ScalarType>::Box3x Box3x;
00038
00039 const Point3i &ISize() {return this->siz;}
00040
00041 ScalarType Val(const int &x,const int &y,const int &z) const {
00042 return cV(x,y,z).V();
00043
00044 }
00045
00046 ScalarType &Val(const int &x,const int &y,const int &z) {
00047 return V(x,y,z).V();
00048
00049 }
00050
00051 VOX_TYPE &V(const int &x,const int &y,const int &z) {
00052 return Vol[x+y*this->siz[0]+z*this->siz[0]*this->siz[1]];
00053 }
00054
00055 VOX_TYPE &V(const Point3i &pi) {
00056 return Vol[ pi[0] + pi[1]*this->siz[0] + pi[2]*this->siz[0]*this->siz[1] ];
00057 }
00058
00059 const VOX_TYPE &cV(const int &x,const int &y,const int &z) const {
00060 return Vol[x+y*this->siz[0]+z*this->siz[0]*this->siz[1]];
00061 }
00062
00063 bool ValidCell(const Point3i & , const Point3i & ) const { return true;}
00064
00065 template < class VertexPointerType >
00066 void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00067 { GetIntercept<VertexPointerType,XAxis>(p1,p2,v,thr); }
00068
00069 template < class VertexPointerType >
00070 void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00071 { GetIntercept<VertexPointerType,YAxis>(p1,p2,v,thr); }
00072
00073 template < class VertexPointerType >
00074 void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00075 { GetIntercept<VertexPointerType,ZAxis>(p1,p2,v,thr); }
00076
00079
00080 std::vector<VoxelType> Vol;
00081
00082 typedef enum { XAxis=0,YAxis=1,ZAxis=2} VolumeAxis;
00083
00084 template < class VertexPointerType, VolumeAxis AxisVal >
00085 void GetIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointerType &v, const float thr)
00086 {
00087 float f1 = V(p1).V()-thr;
00088 float f2 = V(p2).V()-thr;
00089 float u = (float) f1/(f1-f2);
00090 if(AxisVal==XAxis) v->P().X() = (float) p1.X()*(1-u) + u*p2.X();
00091 else v->P().X() = (float) p1.X();
00092 if(AxisVal==YAxis) v->P().Y() = (float) p1.Y()*(1-u) + u*p2.Y();
00093 else v->P().Y() = (float) p1.Y();
00094 if(AxisVal==ZAxis) v->P().Z() = (float) p1.Z()*(1-u) + u*p2.Z();
00095 else v->P().Z() = (float) p1.Z();
00096 this->IPfToPf(v->P(),v->P());
00097 if(VoxelType::HasNormal()) v->N().Import(V(p1).N()*(1-u) + V(p2).N()*u);
00098 }
00099
00100
00101
00102 void Init(Point3i _sz, Box3x bb)
00103 {
00104 this->siz=_sz;
00105 this->bbox = bb;
00106 Vol.resize(this->siz[0]*this->siz[1]*this->siz[2]);
00107 this->ComputeDimAndVoxel();
00108 }
00109
00110
00111
00112 };
00113 template <class _ScalarType=float>
00114 class SimpleVoxel
00115 {
00116 private:
00117 _ScalarType _v;
00118 public:
00119 typedef _ScalarType ScalarType;
00120 ScalarType &V() {return _v;}
00121 ScalarType V() const {return _v;}
00122 static bool HasNormal() {return false;}
00123 vcg::Point3<ScalarType> N() const {return Point3<ScalarType>(0,0,0);}
00124 vcg::Point3<ScalarType> &N() { static Point3<ScalarType> _p(0,0,0); return _p;}
00125 };
00126
00127 template <class _ScalarType=float>
00128 class SimpleVoxelWithNormal
00129 {
00130 private:
00131 _ScalarType _v;
00132 vcg::Point3<_ScalarType> _n;
00133 public:
00134 typedef _ScalarType ScalarType;
00135 ScalarType &V() {return _v;}
00136 ScalarType V() const {return _v;}
00137 vcg::Point3<ScalarType> &N() {return _n;}
00138 vcg::Point3<ScalarType> N() const {return _n;}
00139 static bool HasNormal() {return true;}
00140
00141 };
00142
00143
00144 namespace tri {
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 template <class MeshType, class VolumeType>
00156 class TrivialWalker
00157 {
00158 private:
00159 typedef int VertexIndex;
00160 typedef typename MeshType::ScalarType ScalarType;
00161 typedef typename MeshType::VertexPointer VertexPointer;
00162 public:
00163
00164
00165
00166
00167
00168 void Init(VolumeType &volume)
00169 {
00170 Init(volume,Box3i(Point3i(0,0,0),volume.ISize()));
00171 }
00172
00173 void Init(VolumeType &, Box3i subbox)
00174 {
00175 _bbox = subbox;
00176 _slice_dimension = _bbox.DimX()*_bbox.DimZ();
00177
00178 _x_cs = new VertexIndex[ _slice_dimension ];
00179 _y_cs = new VertexIndex[ _slice_dimension ];
00180 _z_cs = new VertexIndex[ _slice_dimension ];
00181 _x_ns = new VertexIndex[ _slice_dimension ];
00182 _z_ns = new VertexIndex[ _slice_dimension ];
00183
00184 }
00185
00186 ~TrivialWalker()
00187 {_thr=0;}
00188
00189 template<class EXTRACTOR_TYPE>
00190 void BuildMesh(MeshType &mesh, VolumeType &volume, EXTRACTOR_TYPE &extractor, const float threshold, vcg::CallBackPos * cb=0)
00191 {
00192 Init(volume);
00193 _volume = &volume;
00194 _mesh = &mesh;
00195 _mesh->Clear();
00196 _thr=threshold;
00197 vcg::Point3i p1, p2;
00198
00199 Begin();
00200 extractor.Initialize();
00201 for (int j=_bbox.min.Y(); j<(_bbox.max.Y()-1)-1; j+=1)
00202 {
00203
00204 if(cb && ((j%10)==0) ) cb(j*_bbox.DimY()/100.0,"Marching volume");
00205
00206 for (int i=_bbox.min.X(); i<(_bbox.max.X()-1)-1; i+=1)
00207 {
00208 for (int k=_bbox.min.Z(); k<(_bbox.max.Z()-1)-1; k+=1)
00209 {
00210 p1.X()=i; p1.Y()=j; p1.Z()=k;
00211 p2.X()=i+1; p2.Y()=j+1; p2.Z()=k+1;
00212 if(volume.ValidCell(p1,p2))
00213 extractor.ProcessCell(p1, p2);
00214 }
00215 }
00216 NextSlice();
00217 }
00218 extractor.Finalize();
00219 _volume = NULL;
00220 _mesh = NULL;
00221 }
00222
00223 float V(int pi, int pj, int pk)
00224 {
00225 return _volume->Val(pi, pj, pk)-_thr;
00226 }
00227
00228 bool Exist(const vcg::Point3i &p0, const vcg::Point3i &p1, VertexPointer &v)
00229 {
00230 int pos = p0.X()+p0.Z()*_bbox.max.X();
00231 int vidx;
00232
00233 if (p0.X()!=p1.X())
00234 vidx = (p0.Y()==_current_slice) ? _x_cs[pos] : _x_ns[pos];
00235 else if (p0.Y()!=p1.Y())
00236 vidx = _y_cs[pos];
00237 else if (p0.Z()!=p1.Z())
00238 vidx = (p0.Y()==_current_slice)? _z_cs[pos] : _z_ns[pos];
00239 else
00240 assert(false);
00241
00242 v = (vidx!=-1)? &_mesh->vert[vidx] : NULL;
00243 return v!=NULL;
00244 }
00245
00246 void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00247 {
00248 int i = p1.X() - _bbox.min.X();
00249 int z = p1.Z() - _bbox.min.Z();
00250 VertexIndex index = i+z*_bbox.max.X();
00251 VertexIndex pos;
00252 if (p1.Y()==_current_slice)
00253 {
00254 if ((pos=_x_cs[index])==-1)
00255 {
00256 _x_cs[index] = (VertexIndex) _mesh->vert.size();
00257 pos = _x_cs[index];
00258 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00259 v = &_mesh->vert[pos];
00260 _volume->GetXIntercept(p1, p2, v, _thr);
00261 return;
00262 }
00263 }
00264 if (p1.Y()==_current_slice+1)
00265 {
00266 if ((pos=_x_ns[index])==-1)
00267 {
00268 _x_ns[index] = (VertexIndex) _mesh->vert.size();
00269 pos = _x_ns[index];
00270 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00271 v = &_mesh->vert[pos];
00272 _volume->GetXIntercept(p1, p2, v,_thr);
00273 return;
00274 }
00275 }
00276 assert(pos >=0 && size_t(pos)< _mesh->vert.size());
00277 v = &_mesh->vert[pos];
00278 }
00279 void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00280 {
00281 int i = p1.X() - _bbox.min.X();
00282 int z = p1.Z() - _bbox.min.Z();
00283 VertexIndex index = i+z*_bbox.max.X();
00284 VertexIndex pos;
00285 if ((pos=_y_cs[index])==-1)
00286 {
00287 _y_cs[index] = (VertexIndex) _mesh->vert.size();
00288 pos = _y_cs[index];
00289 Allocator<MeshType>::AddVertices( *_mesh, 1);
00290 v = &_mesh->vert[ pos ];
00291 _volume->GetYIntercept(p1, p2, v,_thr);
00292 }
00293 v = &_mesh->vert[pos];
00294 }
00295 void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00296 {
00297 int i = p1.X() - _bbox.min.X();
00298 int z = p1.Z() - _bbox.min.Z();
00299 VertexIndex index = i+z*_bbox.max.X();
00300 VertexIndex pos;
00301 if (p1.Y()==_current_slice)
00302 {
00303 if ((pos=_z_cs[index])==-1)
00304 {
00305 _z_cs[index] = (VertexIndex) _mesh->vert.size();
00306 pos = _z_cs[index];
00307 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00308 v = &_mesh->vert[pos];
00309 _volume->GetZIntercept(p1, p2, v,_thr);
00310 return;
00311 }
00312 }
00313 if (p1.Y()==_current_slice+1)
00314 {
00315 if ((pos=_z_ns[index])==-1)
00316 {
00317 _z_ns[index] = (VertexIndex) _mesh->vert.size();
00318 pos = _z_ns[index];
00319 Allocator<MeshType>::AddVertices( *_mesh, 1 );
00320 v = &_mesh->vert[pos];
00321 _volume->GetZIntercept(p1, p2, v,_thr);
00322 return;
00323 }
00324 }
00325 v = &_mesh->vert[pos];
00326 }
00327
00328 protected:
00329 Box3i _bbox;
00330
00331 int _slice_dimension;
00332 int _current_slice;
00333
00334 VertexIndex *_x_cs;
00335 VertexIndex *_y_cs;
00336 VertexIndex *_z_cs;
00337 VertexIndex *_x_ns;
00338 VertexIndex *_z_ns;
00339
00340 MeshType *_mesh;
00341 VolumeType *_volume;
00342
00343 float _thr;
00344 void NextSlice()
00345 {
00346 memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00347 memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
00348 memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00349
00350 std::swap(_x_cs, _x_ns);
00351 std::swap(_z_cs, _z_ns);
00352
00353 _current_slice += 1;
00354 }
00355
00356 void Begin()
00357 {
00358 _current_slice = _bbox.min.Y();
00359
00360 memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00361 memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
00362 memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00363 memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex));
00364 memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex));
00365
00366 }
00367 };
00368 }
00369 }
00370 #endif // __VCGTEST_WALKER