diff --git a/vcg/complex/trimesh/append.h b/vcg/complex/trimesh/append.h index 7c13cffd..840461ac 100644 --- a/vcg/complex/trimesh/append.h +++ b/vcg/complex/trimesh/append.h @@ -20,33 +20,6 @@ * for more details. * * * ****************************************************************************/ -/**************************************************************************** - History - -$Log: not supported by cvs2svn $ -Revision 1.7 2008/01/28 08:39:56 cignoni -added management of normals - -Revision 1.6 2007/03/12 15:38:03 tarini -Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. - -Revision 1.5 2006/05/25 04:40:57 cignoni -Updated HasPerFaceColor/Quality to the new style with mesh param. - -Revision 1.4 2006/04/11 13:51:21 zifnab1974 -commented out one function which does not compile on linux with gcc 3.4.5 - -Revision 1.3 2006/01/30 09:00:40 cignoni -Corrected use of HasPerWedgeTexture - -Revision 1.2 2006/01/22 17:08:50 cignoni -Bug due to wrong compuation of size of auxiliary vector (vn instead of vert.size() ) - -Revision 1.1 2006/01/11 15:45:21 cignoni -Initial Release - -****************************************************************************/ - #ifndef __VCGLIB_APPEND #define __VCGLIB_APPEND @@ -61,127 +34,284 @@ template class Append { public: - typedef typename MeshLeft::ScalarType ScalarLeft; - typedef typename MeshLeft::CoordType CoordLeft; - typedef typename MeshLeft::VertexType VertexLeft; - typedef typename MeshLeft::FaceType FaceLeft; - typedef typename MeshLeft::VertexPointer VertexPointerLeft; - typedef typename MeshLeft::VertexIterator VertexIteratorLeft; - typedef typename MeshLeft::FaceIterator FaceIteratorLeft; + typedef typename MeshLeft::ScalarType ScalarLeft; + typedef typename MeshLeft::CoordType CoordLeft; + typedef typename MeshLeft::VertexType VertexLeft; + typedef typename MeshLeft::EdgeType EdgeLeft; + typedef typename MeshLeft::FaceType FaceLeft; + typedef typename MeshLeft::HEdgeType HEdgeLeft; + typedef typename MeshLeft::VertexPointer VertexPointerLeft; + typedef typename MeshLeft::VertexIterator VertexIteratorLeft; + typedef typename MeshLeft::EdgeIterator EdgeIteratorLeft; + typedef typename MeshLeft::HEdgeIterator HEdgeIteratorLeft; + typedef typename MeshLeft::FaceIterator FaceIteratorLeft; - typedef typename MeshRight::ScalarType ScalarRight; - typedef typename MeshRight::CoordType CoordRight; - typedef typename MeshRight::VertexType VertexRight; - typedef typename MeshRight::FaceType FaceRight; + + typedef typename MeshRight::ScalarType ScalarRight; + typedef typename MeshRight::CoordType CoordRight; + typedef typename MeshRight::VertexType VertexRight; + typedef typename MeshRight::EdgeType EdgeRight; + typedef typename MeshRight::HEdgeType HEdgeRight; + typedef typename MeshRight::FaceType FaceRight; typedef typename MeshRight::VertexPointer VertexPointerRight; typedef typename MeshRight::VertexIterator VertexIteratorRight; + typedef typename MeshRight::EdgeIterator EdgeIteratorRight; + typedef typename MeshRight::HEdgeIterator HEdgeIteratorRight; typedef typename MeshRight::FaceIterator FaceIteratorRight; - typedef typename MeshRight::FacePointer FacePointerRight; + typedef typename MeshRight::FacePointer FacePointerRight; -static void ImportFace(MeshLeft &ml, MeshRight &mr, FaceLeft &fl, const FaceRight &fr, std::vector &remap) -{ - fl.template ImportLocal(fr); - fl.V(0)=&ml.vert[remap[ Index(mr,fr.V(0))]]; - fl.V(1)=&ml.vert[remap[ Index(mr,fr.V(1))]]; - fl.V(2)=&ml.vert[remap[ Index(mr,fr.V(2))]]; + struct Remap{ + std::vector vert,face,edge, hedge; + }; - if(HasPerWedgeTexCoord(mr) && HasPerWedgeTexCoord(ml)) - for(int i=0;i<3;++i){ - fl.WT(i).P()=fr.cWT(i).P(); - fl.WT(i).N()=fr.cWT(i).N()+ml.textures.size(); - } -} + static void ImportVertexAdj(MeshLeft &ml, MeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap){ + // Vertex to Edge Adj + if(vcg::tri::HasVEAdjacency(ml) && vcg::tri::HasVEAdjacency(mr)){ + size_t i = Index(mr,vr.cVEp()); + vl.VEp() = ((i<0) || (i>ml.edge.size()))? 0 : &ml.edge[remap.edge[i]]; + vl.VEi() = vr.VEi(); + } + + // Vertex to Face Adj + if(vcg::tri::HasVFAdjacency(ml) && vcg::tri::HasVFAdjacency(mr)){ + size_t i = Index(mr,vr.cVFp()); + vl.VFp() = ((i<0) || (i>ml.edge.size()))? 0 :&ml.face[remap.face[i]]; + vl.VFi() = vr.VFi(); + } + + // Vertex to HEdge Adj + if(vcg::tri::HasVHAdjacency(ml) && vcg::tri::HasVHAdjacency(mr)){ + vl.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]]; + vl.VHi() = vr.VHi(); + } + } + + static void ImportEdgeAdj(MeshLeft &ml, MeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap){ + + // Edge to Vertex Adj + if(vcg::tri::HasEVAdjacency(ml) && vcg::tri::HasEVAdjacency(mr)){ + el.EVp(0) = &ml.vert[remap.vert[Index(mr,er.cEVp(0))]]; + el.EVp(1) = &ml.vert[remap.vert[Index(mr,er.cEVp(1))]]; + } + + // Edge to Edge Adj + if(vcg::tri::HasEEAdjacency(ml) && vcg::tri::HasEEAdjacency(mr)) + for(unsigned int i = 0; i < 2; ++i) + { + size_t i = Index(mr,er.cEEp(i)); + el.EEp(i) = ((i<0) || (i>ml.edge.size()))? 0 : &ml.edge[remap.edge[i]]; + el.EEi(i) = er.cEEi(i); + } + + // Edge to Face Adj + if(vcg::tri::HasEFAdjacency(ml) && vcg::tri::HasEFAdjacency(mr)){ + el.EFp() = &ml.face[remap.face[Index(mr,er.cEFp())]]; + el.EFi() = er.cEFi(); + } + + // Edge to HEdge Adj + if(vcg::tri::HasEHAdjacency(ml) && vcg::tri::HasEHAdjacency(mr)) + el.EHp() = &ml.hedge[remap.hedge[Index(mr,er.cEHp())]]; + } + + + static void ImportFaceAdj(MeshLeft &ml, MeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap){ + // Face to Vertex Adj + if(vcg::tri::HasFVAdjacency(ml) && vcg::tri::HasFVAdjacency(mr)){ + assert(fl.VN() == fr.VN()); + for(unsigned int i = 0; i < fl.VN(); ++i ) + fl.V(i) = &ml.vert[remap.vert[Index(mr,fr.V(i))]]; + } + + // Face to Edge Adj + if(vcg::tri::HasFEAdjacency(ml) && vcg::tri::HasFEAdjacency(mr)){ + assert(fl.VN() == fr.VN()); + for(unsigned int i = 0; i < fl.VN(); ++i ){ + size_t i = Index(mr,fr.cFEp(i)); + fl.FEp(i) = ((i<0) || (i>ml.edge.size()))? 0 : &ml.edge[remap.edge[i]]; + } + } + + // Face to Face Adj + if(vcg::tri::HasFFAdjacency(ml) && vcg::tri::HasFFAdjacency(mr)){ + assert(fl.VN() == fr.VN()); + for(unsigned int i = 0; i < fl.VN(); ++i ){ + fl.FFp(i) = &ml.face[remap.face[Index(mr,fr.cFFp(i))]]; + fl.FFi(i) = fr.cFFi(i); + } + } + + // Face to HEedge Adj + if(vcg::tri::HasFHAdjacency(ml) && vcg::tri::HasFHAdjacency(mr)) + fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]]; + } + + static void ImportHEdgeAdj(MeshLeft &ml, MeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap){ + // HEdge to Vertex Adj + if(vcg::tri::HasHVAdjacency(ml) && vcg::tri::HasHVAdjacency(mr)) + hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]]; + + // HEdge to Edge Adj + if(vcg::tri::HasHEAdjacency(ml) && vcg::tri::HasHEAdjacency(mr)){ + size_t i = Index(mr,hr.cHEp()) ; + hl.HEp() = ((i<0) || (i>ml.edge.size()))? 0 : &ml.edge[remap.edge[i]]; + } + + // HEdge to Face Adj + if(vcg::tri::HasHFAdjacency(ml) && vcg::tri::HasHFAdjacency(mr)) + hl.HFp() = &ml.face[remap.face[Index(mr,hr.cHFp())]]; + + + // HEdge to Opposite HEdge Adj + if(vcg::tri::HasHOppAdjacency(ml) && vcg::tri::HasHOppAdjacency(mr)) + hl.HOp() = &ml.hedge[remap.hedge[Index(mr,hr.cHOp())]]; + + // HEdge to Next HEdge Adj + if(vcg::tri::HasHNextAdjacency(ml) && vcg::tri::HasHNextAdjacency(mr)) + hl.HNp() = &ml.hedge[remap.hedge[Index(mr,hr.cHNp())]]; + + // HEdge to Next HEdge Adj + if(vcg::tri::HasHPrevAdjacency(ml) && vcg::tri::HasHPrevAdjacency(mr)) + hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]]; + } + +//static void ImportFace(MeshLeft &ml, MeshRight &mr, FaceLeft &fl, const FaceRight &fr, std::vector &remap) +//{ +// fl.template ImportData(fr); +// fl.V(0)=&ml.vert[remap[ Index(mr,fr.V(0))]]; +// fl.V(1)=&ml.vert[remap[ Index(mr,fr.V(1))]]; +// fl.V(2)=&ml.vert[remap[ Index(mr,fr.V(2))]]; +// +// if(HasPerWedgeTexCoord(mr) && HasPerWedgeTexCoord(ml)) +// for(int i=0;i<3;++i){ +// fl.WT(i).P()=fr.cWT(i).P(); +// fl.WT(i).N()=fr.cWT(i).N()+ml.textures.size(); +// } +//} // Append Right Mesh to the Left Mesh // Append::Mesh(ml, mr) is equivalent to ml += mr. // Note MeshRigth could be costant... -static void Mesh(MeshLeft& ml, MeshRight& mr, const bool selected = false, const bool copyUnrefFlag=false) -{ - // remap[i] keep where the position of where the i-th vertex of meshright has landed in meshleft - std::vector remap(mr.vert.size(),-1); - - if(copyUnrefFlag) // copy ALL the vertices of MR onto ML - { - VertexIteratorRight vi; - for(vi=mr.vert.begin();vi!=mr.vert.end();++vi) - { - int vind=Index(mr,*vi); - if(remap[vind]==-1) - { - VertexIteratorLeft vp; - vp=Allocator::AddVertices(ml,1); - (*vp).ImportLocal(*(vi)); - remap[vind]=Index(ml,*vp); - } - } - } - // first loop to find the referenced vertices and copy them preparing the remap vector - FaceIteratorRight fi; - int FaceToAdd=0; - for(fi=mr.face.begin();fi!=mr.face.end();++fi) - if((!(*fi).IsD()) && (!selected || (*fi).IsS() )) - { - ++FaceToAdd; - for(int i=0;i<3;++i) - { - int vind=Index(mr, *(*fi).V(i)); - if(remap[vind]==-1) - { - VertexIteratorLeft vp; - vp=Allocator::AddVertices(ml,1); - (*vp).ImportLocal(*(*fi).V(i)); - remap[vind]=Index(ml,*vp); - } - } - } - // second loop copy the faces updating the vertex references - FaceIteratorLeft fp=Allocator::AddFaces(ml,FaceToAdd); - for(fi=mr.face.begin();fi!=mr.face.end();++fi) - if(!(*fi).IsD() && (!selected || (*fi).IsS() )) - { - ImportFace(ml,mr,(*fp),(*fi),remap); - ++fp; - } - // At the end concatenate the vector with texture names. - ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end()); + +static void Mesh(MeshLeft& ml, MeshRight& mr, const bool selected = false){ + + // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr + // and build the remapping for all + + Remap remap; + + // vertex + remap.vert.resize(mr.vert.size(),-1); + VertexIteratorRight vi; + for(vi=mr.vert.begin();vi!=mr.vert.end();++vi) + if(!selected || (*vi).IsS()) + { + int ind=Index(mr,*vi); + if(remap.vert[ind]==-1){ + VertexIteratorLeft vp; + vp=Allocator::AddVertices(ml,1); + (*vp).ImportData(*(vi)); + remap.vert[ind]=Index(ml,*vp); + } + } + + // edge + remap.edge.resize(mr.edge.size(),-1); + EdgeIteratorRight ei; + for(ei=mr.edge.begin(); ei!=mr.edge.end();++ei) + if(!selected || (*ei).IsS()) + { + int ind=Index(mr,*ei); + if(remap.edge[ind]==-1){ + EdgeIteratorLeft ep; + ep=Allocator::AddEdges(ml,1); + (*ep).ImportData(*(ei)); + remap.edge[ind]=Index(ml,*ep); + } + } + + // face + remap.face.resize(mr.face.size(),-1); + FaceIteratorRight fi; + for(fi=mr.face.begin();fi!=mr.face.end();++fi) + if(!selected || (*fi).IsS()) + { + int ind=Index(mr,*fi); + if(remap.face[ind]==-1){ + FaceIteratorLeft fp; + fp=Allocator::AddFaces(ml,1); + (*fp).ImportData(*(fi)); + remap.face[ind]=Index(ml,*fp); + } + } + + // hedge + remap.hedge.resize(mr.hedge.size(),-1); + HEdgeIteratorRight hi; + for(hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) + if(!selected || (*hi).IsS()) + { + int ind=Index(mr,*hi); + if(remap.hedge[ind]==-1){ + HEdgeIteratorLeft hp; + hp=Allocator::AddHEdges(ml,1); + (*hp).ImportData(*(hi)); + remap.hedge[ind]=Index(ml,*hp); + } + } + + // phase 2. + // copy data from ml to its corresponding elements in ml and adjacencies + + // vertex + for(vi=mr.vert.begin();vi!=mr.vert.end();++vi) + if(!selected || (*vi).IsS()){ + ml.vert[remap.vert[Index(mr,*vi)]].ImportData(*vi); + ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,*vi)]],*vi,remap); + } + + // edge + for(ei=mr.edge.begin();ei!=mr.edge.end();++ei) + if(!selected || (*ei).IsS()){ + ml.edge[remap.edge[Index(mr,*ei)]].ImportData(*ei); + ImportEdgeAdj(ml,mr,ml.edge[remap.edge[Index(mr,*ei)]],*ei,remap); + } + + // face + for(fi=mr.face.begin();fi!=mr.face.end();++fi) + if(!selected || (*fi).IsS()){ + ml.face[remap.face[Index(mr,*fi)]].ImportData(*fi); + ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,*fi)]],*fi,remap); + } + + // hedge + for(hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) + if(!selected || (*hi).IsS()){ + ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi); + ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,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 + + // to be done. + // note: we need to assign attribute values without knowing their type + + + } -// static void Subset(MeshLeft& ml, std::vector & vfpr) -// { -// // remap[i] keep where the position of where the i-th vertex of meshright has landed in meshleft -// std::vector remap(mr.vert.size(),-1); - -// // first loop to find the referenced vertices and copy them preparing the remap vector -// typename std::vector::iterator fi; -// int FaceToAdd=0; -// for(fi=vfpr.begin();fi!=vfpr.end();++fi) -// if(!(*fi)->IsD()) -// { -// FaceToAdd++; -// for(int i=0;i<3;++i) -// { -// int vind=Index(mr, *(**fi).V(i)); -// if(remap[vind]==-1) -// { -// VertexIteratorLeft vp; -// vp=Allocator::AddVertices(ml,1); -// ImportVertex((*vp),*(**fi).V(i)); -// remap[vind]=Index(ml,*vp); -// } -// } -// } -// // second loop copy the faces updating the vertex references -// FaceIteratorLeft fp=Allocator::AddFaces(ml,FaceToAdd); -// for(fi=vfpr.begin();fi!=vfpr.end();++fi) -// if(!(*fi).IsD()) -// { -// ImportFace(ml,mr,(*fp),(*fi),remap); -// ++fp; -// } -// } - - static void Selected(MeshLeft& ml, MeshRight& mr) { Mesh(ml,mr,true);