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