00001 #ifndef __VCGTEST_WALKER
00002 #define __VCGTEST_WALKER
00003
00004 #include "Definitions.h"
00005 #include "Volume.h"
00006
00007
00008
00009
00010
00011
00012
00013
00014 class Walker
00015 {
00016 private:
00017 typedef int VertexIndex;
00018
00019 public:
00020 Walker(const BoundingBox &bbox, const vcg::Point3i &resolution)
00021 {
00022 _bbox = bbox;
00023 _resolution = resolution;
00024 _cell_size.X() = _bbox.DimX()/_resolution.X();
00025 _cell_size.Y() = _bbox.DimY()/_resolution.Y();
00026 _cell_size.Z() = _bbox.DimZ()/_resolution.Z();
00027 _slice_dimension = resolution.X()*resolution.Z();
00028
00029 _x_cs = new VertexIndex[ _slice_dimension ];
00030 _y_cs = new VertexIndex[ _slice_dimension ];
00031 _z_cs = new VertexIndex[ _slice_dimension ];
00032 _x_ns = new VertexIndex[ _slice_dimension ];
00033 _z_ns = new VertexIndex[ _slice_dimension ];
00034 _v_cs = new float[_slice_dimension];
00035 _v_ns = new float[_slice_dimension];
00036
00037 };
00038
00039 ~Walker()
00040 {}
00041
00042 template<class EXTRACTOR_TYPE>
00043 void BuildMesh(Mesh &mesh, Volume &volume, EXTRACTOR_TYPE &extractor)
00044 {
00045 _volume = &volume;
00046 _mesh = &mesh;
00047 _mesh->Clear();
00048 vcg::Point3i p1, p2;
00049
00050 Begin();
00051 extractor.Initialize();
00052 for (int j=_bbox.min.Y(); j<_bbox.max.Y()-_cell_size.Y(); j+=_cell_size.Y())
00053 {
00054 for (int i=_bbox.min.X(); i<_bbox.max.X()-_cell_size.X(); i+=_cell_size.X())
00055 {
00056 for (int k=_bbox.min.Z(); k<_bbox.max.Z()-_cell_size.Z(); k+=_cell_size.Z())
00057 {
00058 p1.X()=i; p1.Y()=j; p1.Z()=k;
00059 p2.X()=i+_cell_size.X(); p2.Y()=j+_cell_size.Y(); p2.Z()=k+_cell_size.Z();
00060 extractor.ProcessCell(p1, p2);
00061 }
00062 }
00063 NextSlice();
00064 }
00065 extractor.Finalize();
00066 _volume = NULL;
00067 _mesh = NULL;
00068 };
00069
00070 float V(int pi, int pj, int pk)
00071 {
00072 int i = pi - _bbox.min.X();
00073 int k = pk - _bbox.min.Z();
00074 return (pj==_current_slice) ? _v_cs[i+k*_resolution.X()] : _v_ns[i+k*_resolution.X()];
00075 }
00076
00077 bool Exist(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00078 {
00079 int i_idx = p1.X()-_bbox.min.X();
00080 int k_idx = p2.Z()-_bbox.min.Z();
00081 int index = i_idx+k_idx*_resolution.X();
00082 if (p1.X()!=p2.X())
00083 return (p1.Y()==_current_slice)? _x_cs[index]!=-1 : _x_ns[index]!=-1;
00084 else if (p1.Y()!=p2.Y())
00085 return _y_cs[index]!=-1;
00086 else if (p1.Z()!=p2.Z())
00087 return (p1.Y()==_current_slice)? _z_cs[index]!=-1 : _z_ns[index]!=-1;
00088
00089 assert(false);
00090 return false;
00091 }
00092
00093 void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00094 {
00095 int i = p1.X() - _bbox.min.X();
00096 int z = p1.Z() - _bbox.min.Z();
00097 VertexIndex index = i+z*_resolution.X();
00098 VertexIndex pos;
00099 if (p1.Y()==_current_slice)
00100 {
00101 if ((pos=_x_cs[index])==-1)
00102 {
00103 _x_cs[index] = (VertexIndex) _mesh->vert.size();
00104 pos = _x_cs[index];
00105 Allocator::AddVertices( *_mesh, 1 );
00106 v = &_mesh->vert[pos];
00107 _volume->GetXIntercept(p1, p2, v);
00108 return;
00109 }
00110 }
00111 if (p1.Y()==_current_slice+_cell_size.Y())
00112 {
00113 if ((pos=_x_ns[index])==-1)
00114 {
00115 _x_ns[index] = (VertexIndex) _mesh->vert.size();
00116 pos = _x_ns[index];
00117 Allocator::AddVertices( *_mesh, 1 );
00118 v = &_mesh->vert[pos];
00119 _volume->GetXIntercept(p1, p2, v);
00120 return;
00121 }
00122 }
00123 v = &_mesh->vert[pos];
00124 }
00125 void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00126 {
00127 int i = p1.X() - _bbox.min.X();
00128 int z = p1.Z() - _bbox.min.Z();
00129 VertexIndex index = i+z*_resolution.X();
00130 VertexIndex pos;
00131 if ((pos=_y_cs[index])==-1)
00132 {
00133 _y_cs[index] = (VertexIndex) _mesh->vert.size();
00134 pos = _y_cs[index];
00135 Allocator::AddVertices( *_mesh, 1);
00136 v = &_mesh->vert[ pos ];
00137 _volume->GetYIntercept(p1, p2, v);
00138 }
00139 v = &_mesh->vert[pos];
00140 }
00141 void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v)
00142 {
00143 int i = p1.X() - _bbox.min.X();
00144 int z = p1.Z() - _bbox.min.Z();
00145 VertexIndex index = i+z*_resolution.X();
00146 VertexIndex pos;
00147 if (p1.Y()==_current_slice)
00148 {
00149 if ((pos=_z_cs[index])==-1)
00150 {
00151 _z_cs[index] = (VertexIndex) _mesh->vert.size();
00152 pos = _z_cs[index];
00153 Allocator::AddVertices( *_mesh, 1 );
00154 v = &_mesh->vert[pos];
00155 _volume->GetZIntercept(p1, p2, v);
00156 return;
00157 }
00158 }
00159 if (p1.Y()==_current_slice+_cell_size.Y())
00160 {
00161 if ((pos=_z_ns[index])==-1)
00162 {
00163 _z_ns[index] = (VertexIndex) _mesh->vert.size();
00164 pos = _z_ns[index];
00165 Allocator::AddVertices( *_mesh, 1 );
00166 v = &_mesh->vert[pos];
00167 _volume->GetZIntercept(p1, p2, v);
00168 return;
00169 }
00170 }
00171 v = &_mesh->vert[pos];
00172 }
00173
00174 protected:
00175 BoundingBox _bbox;
00176 vcg::Point3i _resolution;
00177 vcg::Point3i _cell_size;
00178
00179 int _slice_dimension;
00180 int _current_slice;
00181
00182 float *_v_cs;
00183 float *_v_ns;
00184
00185 VertexIndex *_x_cs;
00186 VertexIndex *_y_cs;
00187 VertexIndex *_z_cs;
00188 VertexIndex *_x_ns;
00189 VertexIndex *_z_ns;
00190
00191 Mesh *_mesh;
00192 Volume *_volume;
00193
00194 void NextSlice()
00195 {
00196 memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00197 memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
00198 memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00199
00200 std::swap(_x_cs, _x_ns);
00201 std::swap(_z_cs, _z_ns);
00202 std::swap(_v_cs, _v_ns);
00203
00204 _current_slice += _cell_size.Y();
00205 int j = _current_slice + _cell_size.Y();
00206 int k_idx, i_idx, index;
00207 for (int i=_bbox.min.X(); i<_bbox.max.X(); i+=_cell_size.X())
00208 {
00209 i_idx = i-_bbox.min.X();
00210 for (int k=_bbox.min.Z(); k<_bbox.max.Z(); k+=_cell_size.Z())
00211 {
00212 k_idx = k-_bbox.min.Z();
00213 index = i_idx+k_idx*_resolution.X();
00214 _v_ns[ index ] = _volume->V(i, j, k);
00215 }
00216 }
00217 }
00218
00219 void Begin()
00220 {
00221 _current_slice = _bbox.min.Y();
00222
00223 memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex));
00224 memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex));
00225 memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex));
00226 memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex));
00227 memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex));
00228
00229 int index;
00230 int j = _current_slice;
00231 int i_idx, k_idx;
00232 for (int i=_bbox.min.X(); i<_bbox.max.X(); i+=_cell_size.X())
00233 {
00234 i_idx = i-_bbox.min.X();
00235 for (int k=_bbox.min.Z(); k<_bbox.max.Z(); k+=_cell_size.Z())
00236 {
00237 k_idx = k-_bbox.min.Z();
00238 index = i_idx+k_idx*_resolution.X();
00239 _v_cs[index] = _volume->V(i, j, k);
00240 _v_ns[index] = _volume->V(i, j+_cell_size.Y(), k);
00241 }
00242 }
00243 }
00244 };
00245 #endif // __VCGTEST_WALKER