diff --git a/vcg/complex/algorithms/update/topology.h b/vcg/complex/algorithms/update/topology.h index a71f63e9..13054c40 100644 --- a/vcg/complex/algorithms/update/topology.h +++ b/vcg/complex/algorithms/update/topology.h @@ -295,9 +295,10 @@ static void AllocateEdge(MeshType &m) std::vector fpVec; std::vector eiVec; face::EFStarFF(Edges[i].f,Edges[i].z,fpVec,eiVec); - for(size_t j=0;jFEp(eiVec[j])=&(m.edge[i]); - + for (size_t j = 0; j < fpVec.size(); ++j) { + fpVec[j]->FEp(eiVec[j]) = &(m.edge[i]); + assert(vcg::tri::IsValidPointer(m, fpVec[j]->cFEp(eiVec[j]))); + } // Edges[i].f->FE(Edges[i].z) = &(m.edge[i]); // Connect in loop the non manifold // FaceType* fpit=fp; diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 63c44684..c2db7433 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -475,6 +475,234 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, // } } +static void Mesh(MeshLeft &ml, + ConstMeshRight &mr, + Remap &remap, + const bool selected = false, + const bool adjFlag = false) +{ + // Note that if the the selection of the vertexes is not consistent with the face selection + // the append could build faces referencing non existent vertices + // so it is mandatory that the selection of the vertices reflects the loose selection + // from edges and faces (e.g. if a face is selected all its vertices must be selected). + // note the use of the parameter for preserving existing vertex selection. + if (selected) { + assert(adjFlag == false + || ml.IsEmpty()); // It is rather meaningless to partially copy adj relations. + tri::UpdateSelection::VertexFromEdgeLoose(mr, true); + tri::UpdateSelection::VertexFromFaceLoose(mr, true); + } + + // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr + // and build the remapping for all + + // vertex + remap.vert.resize(mr.vert.size(), Remap::InvalidIndex()); + VertexIteratorLeft vp; + size_t svn = UpdateSelection::VertexCount(mr); + if (selected) + vp = Allocator::AddVertices(ml, int(svn)); + else + vp = Allocator::AddVertices(ml, mr.vn); + + for (VertexIteratorRight vi = mr.vert.begin(); vi != mr.vert.end(); ++vi) { + if (!(*vi).IsD() && (!selected || (*vi).IsS())) { + size_t ind = Index(mr, *vi); + remap.vert[ind] = int(Index(ml, *vp)); + ++vp; + } + } + // edge + remap.edge.resize(mr.edge.size(), Remap::InvalidIndex()); + EdgeIteratorLeft ep; + size_t sen = UpdateSelection::EdgeCount(mr); + if (selected) + ep = Allocator::AddEdges(ml, sen); + else + ep = Allocator::AddEdges(ml, mr.en); + + for (EdgeIteratorRight ei = mr.edge.begin(); ei != mr.edge.end(); ++ei) + if (!(*ei).IsD() && (!selected || (*ei).IsS())) { + size_t ind = Index(mr, *ei); + remap.edge[ind] = int(Index(ml, *ep)); + ++ep; + } + + // face + remap.face.resize(mr.face.size(), Remap::InvalidIndex()); + FaceIteratorLeft fp; + size_t sfn = UpdateSelection::FaceCount(mr); + if (selected) + fp = Allocator::AddFaces(ml, sfn); + else + fp = Allocator::AddFaces(ml, mr.fn); + + for (FaceIteratorRight fi = mr.face.begin(); fi != mr.face.end(); ++fi) + if (!(*fi).IsD() && (!selected || (*fi).IsS())) { + size_t ind = Index(mr, *fi); + remap.face[ind] = int(Index(ml, *fp)); + ++fp; + } + + // hedge + remap.hedge.resize(mr.hedge.size(), Remap::InvalidIndex()); + for (HEdgeIteratorRight hi = mr.hedge.begin(); hi != mr.hedge.end(); ++hi) + if (!(*hi).IsD() && (!selected || (*hi).IsS())) { + size_t ind = Index(mr, *hi); + assert(remap.hedge[ind] == Remap::InvalidIndex()); + HEdgeIteratorLeft hp = Allocator::AddHEdges(ml, 1); + (*hp).ImportData(*(hi)); + remap.hedge[ind] = Index(ml, *hp); + } + + remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); + for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if (!(*ti).IsD() && (!selected || (*ti).IsS())) { + size_t idx = Index(mr, *ti); + assert(remap.tetra[idx] == Remap::InvalidIndex()); + TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); + (*tp).ImportData(*ti); + remap.tetra[idx] = Index(ml, *tp); + } + + // phase 2. + // copy data from mr to its corresponding elements in ml and adjacencies + + // vertex + for (VertexIteratorRight vi = mr.vert.begin(); vi != mr.vert.end(); ++vi) + if (!(*vi).IsD() && (!selected || (*vi).IsS())) { + ml.vert[remap.vert[Index(mr, *vi)]].ImportData(*vi); + if (adjFlag) + ImportVertexAdj(ml, mr, ml.vert[remap.vert[Index(mr, *vi)]], *vi, remap); + } + + // edge + for (EdgeIteratorRight ei = mr.edge.begin(); ei != mr.edge.end(); ++ei) + if (!(*ei).IsD() && (!selected || (*ei).IsS())) { + ml.edge[remap.edge[Index(mr, *ei)]].ImportData(*ei); + // Edge to Vertex Adj + EdgeLeft &el = ml.edge[remap.edge[Index(mr, *ei)]]; + if (HasEVAdjacency(ml) && HasEVAdjacency(mr)) { + el.V(0) = &ml.vert[remap.vert[Index(mr, ei->cV(0))]]; + el.V(1) = &ml.vert[remap.vert[Index(mr, ei->cV(1))]]; + } + if (adjFlag) + ImportEdgeAdj(ml, mr, el, *ei, remap); + } + + // face + const size_t textureOffset = ml.textures.size(); + bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset > 0); + for (FaceIteratorRight fi = mr.face.begin(); fi != mr.face.end(); ++fi) + if (!(*fi).IsD() && (!selected || (*fi).IsS())) { + FaceLeft &fl = ml.face[remap.face[Index(mr, *fi)]]; + fl.Alloc(fi->VN()); + if (HasFVAdjacency(ml) && HasFVAdjacency(mr)) { + for (int i = 0; i < fl.VN(); ++i) + fl.V(i) = &ml.vert[remap.vert[Index(mr, fi->cV(i))]]; + } + fl.ImportData(*fi); + if (WTFlag) + for (int i = 0; i < fl.VN(); ++i) + fl.WT(i).n() += short(textureOffset); + if (adjFlag) + ImportFaceAdj(ml, mr, ml.face[remap.face[Index(mr, *fi)]], *fi, remap); + } + + // hedge + for (HEdgeIteratorRight hi = mr.hedge.begin(); hi != mr.hedge.end(); ++hi) + if (!(*hi).IsD() && (!selected || (*hi).IsS())) { + ml.hedge[remap.hedge[Index(mr, *hi)]].ImportData(*hi); + ImportHEdgeAdj(ml, mr, ml.hedge[remap.hedge[Index(mr, *hi)]], *hi, remap, selected); + } + + //tetra + for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if (!(*ti).IsD() && (!selected || (*ti).IsS())) { + TetraLeft &tl = ml.tetra[remap.tetra[Index(mr, *ti)]]; + + if (HasFVAdjacency(ml) && HasFVAdjacency(mr)) { + for (int i = 0; i < 4; ++i) + tl.V(i) = &ml.vert[remap.vert[Index(mr, ti->cV(i))]]; + } + tl.ImportData(*ti); + if (adjFlag) + ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr, *ti)]], *ti, remap); + } + + // phase 3. + // take care of other per mesh data: textures, attributes + + // At the end concatenate the vector with texture names. + ml.textures.insert(ml.textures.end(), mr.textures.begin(), mr.textures.end()); + + // Attributes. Copy only those attributes that are present in both meshes + // Two attributes in different meshes are considered the same if they have the same + // name and the same type. This may be deceiving because they could in fact have + // different semantic, but this is up to the developer. + // If the left mesh has attributes that are not in the right mesh, their values for the elements + // of the right mesh will be uninitialized + + unsigned int id_r; + typename std::set::iterator al, ar; + + // per vertex attributes + for (al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al) + if (!(*al)._name.empty()) { + ar = mr.vert_attr.find(*al); + if (ar != mr.vert_attr.end()) { + id_r = 0; + for (VertexIteratorRight vi = mr.vert.begin(); vi != mr.vert.end(); ++vi, ++id_r) + if (!(*vi).IsD() && (!selected || (*vi).IsS())) + (*al)._handle->CopyValue(remap.vert[Index(mr, *vi)], id_r, (*ar)._handle); + } + } + + // per edge attributes + for (al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al) + if (!(*al)._name.empty()) { + ar = mr.edge_attr.find(*al); + if (ar != mr.edge_attr.end()) { + id_r = 0; + for (EdgeIteratorRight ei = mr.edge.begin(); ei != mr.edge.end(); ++ei, ++id_r) + if (!(*ei).IsD() && (!selected || (*ei).IsS())) + (*al)._handle->CopyValue(remap.edge[Index(mr, *ei)], id_r, (*ar)._handle); + } + } + + // per face attributes + for (al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al) + if (!(*al)._name.empty()) { + ar = mr.face_attr.find(*al); + if (ar != mr.face_attr.end()) { + id_r = 0; + for (FaceIteratorRight fi = mr.face.begin(); fi != mr.face.end(); ++fi, ++id_r) + if (!(*fi).IsD() && (!selected || (*fi).IsS())) + (*al)._handle->CopyValue(remap.face[Index(mr, *fi)], id_r, (*ar)._handle); + } + } + + // per tetra attributes + for (al = ml.tetra_attr.begin(); al != ml.tetra_attr.end(); ++al) + if (!(*al)._name.empty()) { + ar = mr.tetra_attr.find(*al); + if (ar != mr.tetra_attr.end()) { + id_r = 0; + for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r) + if (!(*ti).IsD() && (!selected || (*ti).IsS())) + (*al)._handle->CopyValue(remap.tetra[Index(mr, *ti)], id_r, (*ar)._handle); + } + } + // per mesh attributes + // if both ml and mr have an attribute with the same name, no action is done + // if mr has an attribute that is NOT present in ml, the attribute is added to ml + //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar) + // if(!(*ar)._name.empty()){ + // al = ml.mesh_attr.find(*ar); + // if(al== ml.mesh_attr.end()) + // //... + // } +} /** * @brief MeshAppendConst * @param ml