00001 #ifndef VCG_TRI_ATTRIBUTE_SEAM_H
00002 #define VCG_TRI_ATTRIBUTE_SEAM_H
00003
00004 #include <vector>
00005
00006 #include <vcg/complex/trimesh/allocate.h>
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 namespace vcg
00052 {
00053
00054 namespace tri
00055 {
00056
00057 class AttributeSeam
00058 {
00059 public:
00060
00061 typedef AttributeSeam ThisType;
00062
00063 enum ASMask
00064 {
00065 POSITION_PER_VERTEX = (1 << 0),
00066
00067 NORMAL_PER_VERTEX = (1 << 1),
00068 NORMAL_PER_WEDGE = (1 << 2),
00069 NORMAL_PER_FACE = (1 << 3),
00070
00071 COLOR_PER_VERTEX = (1 << 4),
00072 COLOR_PER_WEDGE = (1 << 5),
00073 COLOR_PER_FACE = (1 << 6),
00074
00075 TEXCOORD_PER_VERTEX = (1 << 7),
00076 TEXCOORD_PER_WEDGE = (1 << 8)
00077 };
00078
00079 template <typename src_trimesh_t, typename dst_trimesh_t>
00080 struct ASExtract
00081 {
00082 const unsigned int mask;
00083
00084 ASExtract(unsigned int vmask = 0) : mask(vmask)
00085 {
00086 ;
00087 }
00088
00089 void operator () (const src_trimesh_t & sm, const typename src_trimesh_t::FaceType & f, int k, const dst_trimesh_t & dm, typename dst_trimesh_t::VertexType & v) const
00090 {
00091 (void)sm;
00092 (void)dm;
00093
00094 const unsigned int m = this->mask;
00095 const typename src_trimesh_t::VertexType & u = *(f.cV(k));
00096
00097 if ((m & AttributeSeam::POSITION_PER_VERTEX) != 0) v.P() = f.cP (k);
00098
00099 if ((m & AttributeSeam::NORMAL_PER_VERTEX) != 0) v.N() = u.cN ( );
00100 if ((m & AttributeSeam::NORMAL_PER_WEDGE) != 0) v.N() = f.cWN(k);
00101 if ((m & AttributeSeam::NORMAL_PER_FACE) != 0) v.N() = f.cN ( );
00102
00103 if ((m & AttributeSeam::COLOR_PER_VERTEX) != 0) v.C() = u.cC ( );
00104 if ((m & AttributeSeam::COLOR_PER_WEDGE) != 0) v.C() = f.cWC(k);
00105 if ((m & AttributeSeam::COLOR_PER_FACE) != 0) v.C() = f.cC ( );
00106
00107 if ((m & AttributeSeam::TEXCOORD_PER_VERTEX) != 0) v.T() = u.cT ( );
00108 if ((m & AttributeSeam::TEXCOORD_PER_WEDGE) != 0) v.T() = f.cWT(k);
00109 }
00110 };
00111
00112 template <typename dst_trimesh_t>
00113 struct ASCompare
00114 {
00115 const unsigned int mask;
00116
00117 ASCompare(unsigned int vmask = 0) : mask(vmask)
00118 {
00119 ;
00120 }
00121
00122 bool operator () (const dst_trimesh_t & sm, const typename dst_trimesh_t::VertexType & u, const typename dst_trimesh_t::VertexType & v) const
00123 {
00124 (void)sm;
00125
00126 const unsigned int m = this->mask;
00127
00128
00129
00130
00131
00132
00133
00134
00135 if ((m & (AttributeSeam::NORMAL_PER_VERTEX | AttributeSeam::NORMAL_PER_WEDGE | AttributeSeam::NORMAL_PER_FACE)) != 0)
00136 {
00137 if (u.cN() != v.cN()) return false;
00138 }
00139
00140 if ((m & (AttributeSeam::COLOR_PER_VERTEX | AttributeSeam::COLOR_PER_WEDGE | AttributeSeam::COLOR_PER_FACE)) != 0)
00141 {
00142 if (u.cC() != v.cC()) return false;
00143 }
00144
00145 if ((m & (AttributeSeam::TEXCOORD_PER_VERTEX | AttributeSeam::TEXCOORD_PER_WEDGE)) != 0)
00146 {
00147 if (u.cT() != v.cT()) return false;
00148 }
00149
00150 return true;
00151 }
00152 };
00153
00154
00155 template <typename src_trimesh_t, typename extract_wedge_attribs_t, typename compare_vertex_attribs_t>
00156 static inline bool SplitVertex(src_trimesh_t & src, extract_wedge_attribs_t v_extract, compare_vertex_attribs_t & v_compare)
00157 {
00158 typedef typename src_trimesh_t::VertexType src_vertex_t;
00159 typedef typename src_trimesh_t::VertexIterator src_vertex_i;
00160 typedef typename src_trimesh_t::FaceType src_face_t;
00161 typedef typename src_trimesh_t::FaceIterator src_face_i;
00162 typedef typename src_trimesh_t::VertContainer src_vertex_container_t;
00163
00164 typedef vcg::tri::Allocator<src_trimesh_t> src_mesh_allocator_t;
00165 typedef typename src_mesh_allocator_t :: template PointerUpdater<typename src_trimesh_t::VertexPointer> src_pointer_updater_t;
00166
00167 if ((src.vn <= 0) || (src.fn <= 0))
00168 {
00169 return true;
00170 }
00171
00172 src_pointer_updater_t pt_upd;
00173 src_vertex_i vi = src_mesh_allocator_t::AddVertices(src, 1, pt_upd);
00174 src_vertex_t * vtx = &(*vi);
00175 src_vertex_t * vtxbase = &(src.vert[0]);
00176
00177 const size_t vertex_count = src.vert.size();
00178 const size_t vertex_pool_size = vertex_count;
00179
00180 std::vector<int> vloc;
00181 vloc.reserve(vertex_pool_size);
00182 vloc.resize(vertex_count, -2);
00183
00184 int vcount = int(src.vert.size());
00185 int idx = 0;
00186
00187 for (src_face_i it=src.face.begin(); it!=src.face.end(); ++it)
00188 {
00189 src_face_t & f = (*it);
00190 if (f.IsD()) continue;
00191
00192 for (int k=0; k<3; ++k)
00193 {
00194 idx = (f.cV(k) - vtxbase);
00195 v_extract(src, f, k, src, *vtx);
00196
00197 if (vloc[idx] == -2)
00198 {
00199 vloc[idx] = -1;
00200 src.vert[idx].ImportData(*vtx);
00201 }
00202 else
00203 {
00204 int vidx = idx;
00205 do
00206 {
00207 if (v_compare(src, src.vert[vidx], *vtx)) break;
00208 vidx = vloc[vidx];
00209 } while (vidx >= 0);
00210
00211 if (vidx < 0)
00212 {
00213 vloc.push_back(vloc[idx]);
00214 vloc[idx] = vcount;
00215
00216 vi = src_mesh_allocator_t::AddVertices(src, 1, pt_upd);
00217 pt_upd.Update(vtx);
00218 pt_upd.Update(vtxbase);
00219
00220 (*vi).ImportData(*vtx);
00221
00222 idx = vcount;
00223 vcount++;
00224 }
00225 else
00226 {
00227 idx = vidx;
00228 }
00229 }
00230
00231 f.V(k) = &(src.vert[idx]);
00232 }
00233 }
00234
00235 src_mesh_allocator_t::DeleteVertex(src, *vtx);
00236
00237 return true;
00238 }
00239
00240
00241 template <typename src_trimesh_t, typename dst_trimesh_t, typename extract_wedge_attribs_t, typename compare_vertex_attribs_t, typename copy_vertex_t>
00242 static inline bool SplitVertex(const src_trimesh_t & src, dst_trimesh_t & dst, extract_wedge_attribs_t & v_extract, compare_vertex_attribs_t & v_compare, copy_vertex_t & v_copy)
00243 {
00244 typedef typename src_trimesh_t::VertexType src_vertex_t;
00245 typedef typename src_trimesh_t::FaceType src_face_t;
00246 typedef typename src_trimesh_t::ConstFaceIterator src_face_ci;
00247
00248 typedef typename dst_trimesh_t::VertContainer dst_vertex_container_t;
00249 typedef typename dst_trimesh_t::VertexType dst_vertex_t;
00250 typedef typename dst_trimesh_t::VertexIterator dst_vertex_i;
00251 typedef typename dst_trimesh_t::FaceType dst_face_t;
00252 typedef typename dst_trimesh_t::FaceIterator dst_face_i;
00253
00254 typedef vcg::tri::Allocator<dst_trimesh_t> dst_mesh_allocator_t;
00255
00256
00257 typedef typename dst_mesh_allocator_t :: template PointerUpdater<typename dst_trimesh_t::VertexPointer> dst_pointer_updater_t;
00258
00259 if (reinterpret_cast<const void *>(&src) == reinterpret_cast<const void *>(&dst))
00260 {
00261 return false;
00262 }
00263
00264 dst.Clear();
00265
00266 if ((src.vn <= 0) || (src.fn <= 0))
00267 {
00268 return true;
00269 }
00270
00271 const size_t vertex_count = src.vert.size();
00272 const size_t vertex_pool_size = vertex_count;
00273
00274 const src_vertex_t * vtxbase = &(src.vert[0]);
00275
00276 std::vector<int> vloc;
00277 vloc.reserve(vertex_pool_size);
00278 vloc.resize(vertex_count, -2);
00279
00280 dst_vertex_i vv;
00281 dst_pointer_updater_t pt_upd;
00282 pt_upd.preventUpdateFlag = true;
00283 dst_mesh_allocator_t::AddVertices(dst, 1 + int(vertex_count), pt_upd);
00284 dst_vertex_t * vtx = &(dst.vert[0]);
00285
00286 dst_face_i fbase = dst_mesh_allocator_t::AddFaces(dst, src.fn);
00287 dst_face_i fi = fbase;
00288
00289 int vcount = int(dst.vert.size());
00290 int idx = 0;
00291
00292 for (src_face_ci it=src.face.begin(); it!=src.face.end(); ++it)
00293 {
00294 const src_face_t & wf = (*it);
00295 if (wf.IsD()) continue;
00296
00297 dst_face_t & vf = (*fi);
00298
00299 for (int k=0; k<3; ++k)
00300 {
00301 idx = (wf.cV(k) - vtxbase);
00302
00303 v_extract(src, wf, k, dst, *vtx);
00304
00305 if (vloc[idx] == -2)
00306 {
00307 vloc[idx] = -1;
00308 v_copy(dst, *vtx, dst.vert[idx]);
00309 }
00310 else
00311 {
00312 int vidx = idx;
00313 do
00314 {
00315 if (v_compare(dst, dst.vert[vidx], *vtx)) break;
00316 vidx = vloc[vidx];
00317 } while (vidx >= 0);
00318
00319 if (vidx < 0)
00320 {
00321 vloc.push_back(vloc[idx]);
00322 vloc[idx] = vcount;
00323
00324 vv = dst_mesh_allocator_t::AddVertices(dst, 1, pt_upd);
00325 pt_upd.Update(vtx);
00326 v_copy(dst, *vtx, *vv);
00327
00328 idx = vcount;
00329 vcount++;
00330 }
00331 else
00332 {
00333 idx = vidx;
00334 }
00335 }
00336
00337 vf.V(k) = reinterpret_cast<dst_vertex_t *>(idx);
00338 }
00339
00340 fi++;
00341 }
00342
00343 {
00344 std::vector<int> tmp;
00345 vloc.swap(tmp);
00346 }
00347
00348 dst_vertex_t * vstart = &(dst.vert[0]);
00349
00350 for (dst_face_i it=fbase; it!=dst.face.end(); ++it)
00351 {
00352 dst_face_t & vf = (*it);
00353
00354 vf.V(0) = vstart + reinterpret_cast<const int>(vf.V(0));
00355 vf.V(1) = vstart + reinterpret_cast<const int>(vf.V(1));
00356 vf.V(2) = vstart + reinterpret_cast<const int>(vf.V(2));
00357 }
00358
00359 dst_mesh_allocator_t::DeleteVertex(dst, *vtx);
00360
00361 return true;
00362 }
00363 };
00364
00365 }
00366
00367 }
00368
00369 #endif // VCG_TRI_ATTRIBUTE_SEAM_H