From fc108322b5ee4021bc83b189dbb50b4b096bea53 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 14:06:10 +0200 Subject: [PATCH 001/140] const correctness for make a copy from a const right Mesh --- vcg/complex/algorithms/update/selection.h | 26 ++- vcg/complex/append.h | 262 +++++++++++++++++++++- vcg/simplex/edge/component.h | 2 + vcg/simplex/face/component.h | 1 + vcg/simplex/face/component_ocf.h | 5 + vcg/simplex/face/component_polygon.h | 1 + vcg/simplex/tetrahedron/component.h | 3 +- vcg/simplex/vertex/component.h | 6 + vcg/simplex/vertex/component_ocf.h | 4 + 9 files changed, 289 insertions(+), 21 deletions(-) diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index ae9d4d04..b6cd1c5f 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -269,34 +269,40 @@ static void Clear(MeshType &m) } /// \brief This function returns the number of selected faces. -static size_t FaceCount(MeshType &m) +static size_t FaceCount(const MeshType &m) { size_t selCnt=0; - for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) - if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; + //for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) + // if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; + for (auto f: m.face) + if(!f.IsD() && f.IsS()) ++selCnt; return selCnt; } /// \brief This function returns the number of selected edges. -static size_t EdgeCount(MeshType &m) +static size_t EdgeCount(const MeshType &m) { size_t selCnt=0; - for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) - if(!(*ei).IsD() && (*ei).IsS()) ++selCnt; + //for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) + // if(!(*ei).IsD() && (*ei).IsS()) ++selCnt; + for (auto e: m.edge) + if(!e.IsD() && e.IsS()) ++selCnt; return selCnt; } /// \brief This function returns the number of selected vertices. -static size_t VertexCount(MeshType &m) +static size_t VertexCount(const MeshType &m) { size_t selCnt=0; - for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) - if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; + //for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) + // if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; + for (auto v: m.vert) + if(!v.IsD() && v.IsS()) ++selCnt; return selCnt; } /// \brief This function returns the number of selected tetras. -static size_t TetraCount (MeshType & m) +static size_t TetraCount (const MeshType & m) { size_t selCnt = 0; ForEachTetra(m, [&selCnt] (TetraType & t) { diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 047214f9..4ea8fd03 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -63,12 +63,12 @@ public: typedef typename ConstMeshRight::FaceType FaceRight; typedef typename ConstMeshRight::TetraType TetraRight; typedef typename ConstMeshRight::TetraPointer TetraPointerRight; - typedef typename ConstMeshRight::TetraIterator TetraIteratorRight; + typedef typename ConstMeshRight::ConstTetraIterator TetraIteratorRight; typedef typename ConstMeshRight::VertexPointer VertexPointerRight; - typedef typename ConstMeshRight::VertexIterator VertexIteratorRight; - typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight; - typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight; - typedef typename ConstMeshRight::FaceIterator FaceIteratorRight; + typedef typename ConstMeshRight::ConstVertexIterator VertexIteratorRight; + typedef typename ConstMeshRight::ConstEdgeIterator EdgeIteratorRight; + typedef typename ConstMeshRight::ConstHEdgeIterator HEdgeIteratorRight; + typedef typename ConstMeshRight::ConstFaceIterator FaceIteratorRight; typedef typename ConstMeshRight::FacePointer FacePointerRight; struct Remap{ @@ -76,7 +76,7 @@ public: std::vector vert, face, edge, hedge, tetra; }; - static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){ + static void ImportVertexAdj(MeshLeft &ml, const ConstMeshRight &mr, VertexLeft &vl, const VertexRight &vr, Remap &remap ){ // Vertex to Edge Adj if(HasVEAdjacency(ml) && HasVEAdjacency(mr) && vr.cVEp() != 0){ size_t i = Index(mr,vr.cVEp()); @@ -105,7 +105,7 @@ public: } } - static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) + static void ImportEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) { // Edge to Edge Adj if(HasEEAdjacency(ml) && HasEEAdjacency(mr)) @@ -129,7 +129,7 @@ public: } - static void ImportFaceAdj(MeshLeft &ml, ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap ) + static void ImportFaceAdj(MeshLeft &ml, const ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap ) { // Face to Edge Adj if(HasFEAdjacency(ml) && HasFEAdjacency(mr)){ @@ -183,7 +183,7 @@ public: fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]]; } - static void ImportHEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){ + static void ImportHEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){ // HEdge to Vertex Adj if(HasHVAdjacency(ml) && HasHVAdjacency(mr)) hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]]; @@ -214,7 +214,7 @@ public: hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]]; } - static void ImportTetraAdj(MeshLeft &ml, ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap ) + static void ImportTetraAdj(MeshLeft &ml, const ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap ) { // Tetra to Tetra Adj if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){ @@ -476,6 +476,241 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, // } } +/** + * @brief MeshAppendConst + * @param ml + * @param mr + * + * This is function is similar with the Mesh function, but does not + * never update selections. In some cases, after the append, + * selection of vertices may be inconsistent with face selection, + * as explained above. + * To avoid this, before using this function, call the following functions: + * + * \code{.cpp} + * vcg::tri::UpdateSelection::VertexFromEdgeLoose(mr,true); + * vcg::tri::UpdateSelection::VertexFromFaceLoose(mr,true); + * \endcode + * + * or, use the Mesh function that takes a non-const Right Mesh argument. + */ +static void MeshAppendConst( + MeshLeft& ml, + const ConstMeshRight& mr, + const bool selected = false, + const bool adjFlag = 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(), 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< PointerToAttribute >::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 Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected elements are copied. */ @@ -485,6 +720,13 @@ static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, cons Mesh(ml,mr,selected,adjFlag); ml.bbox.Import(mr.bbox); } + +static void MeshCopyConst(MeshLeft& ml, const ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) +{ + ml.Clear(); + MeshAppendConst(ml,mr,selected,adjFlag); + ml.bbox.Import(mr.bbox); +} /*! \brief %Append only the selected elements of second mesh to the first one. It is just a wrap of the main Append::Mesh() diff --git a/vcg/simplex/edge/component.h b/vcg/simplex/edge/component.h index a78ca4c6..69d32765 100644 --- a/vcg/simplex/edge/component.h +++ b/vcg/simplex/edge/component.h @@ -78,6 +78,7 @@ public: typename T::EdgePointer &VEp(const int & ) { static typename T::EdgePointer ep=0; assert(0); return ep; } typename T::EdgePointer cVEp(const int & ) const { static typename T::EdgePointer ep=0; assert(0); return ep; } int &VEi(const int &){static int z=0; assert(0); return z;} + int VEi(const int &) const {static int z=0; assert(0); return z;} int cVEi(const int &) const {static int z=0; assert(0); return z;} static bool HasVEAdjacency() { return false; } @@ -278,6 +279,7 @@ public: typename T::EdgePointer &VEp(const int & i) {return _ep[i]; } typename T::EdgePointer cVEp(const int & i) const {return _ep[i]; } int &VEi(const int & i){ return _zp[i];} + int VEi(const int & i)const {return _zp[i];} int cVEi(const int &i )const {return _zp[i];} template < class LeftV> diff --git a/vcg/simplex/face/component.h b/vcg/simplex/face/component.h index ebdc3739..da731066 100644 --- a/vcg/simplex/face/component.h +++ b/vcg/simplex/face/component.h @@ -114,6 +114,7 @@ public: typename T::HEdgePointer &FHp() { static typename T::HEdgePointer fp=0; assert(0); return fp; } typename T::HEdgePointer cFHp() const { static typename T::HEdgePointer fp=0; assert(0); return fp; } char &VFi(int) { static char z=0; assert(0); return z;} + char VFi(int) const { static char z=0; assert(0); return z;} char &FFi(int) { static char z=0; assert(0); return z;} char cVFi(int) const { static char z=0; assert(0); return z;} char cFFi(int) const { static char z=0; assert(0); return z;} diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index bf4c3fb1..a09e84f7 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -408,6 +408,11 @@ public: return (*this).Base().AV[(*this).Index()]._zp[j]; } + char VFi(const int j) const { + assert((*this).Base().VFAdjacencyEnabled); + return (*this).Base().AV[(*this).Index()]._zp[j]; + } + char cVFi(const int j) const { assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp[j]; diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index dde27016..8ac67f47 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -136,6 +136,7 @@ public: typename T::FacePointer const VFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } typename T::FacePointer const cVFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } char &VFi(const int j) {return _vfiP[j]; } + char VFi(const int j) const {return _vfiP[j]; } template void ImportData(const LeftF & leftF){T::ImportData(leftF);} inline void Alloc(const int & ns) { diff --git a/vcg/simplex/tetrahedron/component.h b/vcg/simplex/tetrahedron/component.h index d2d8c878..7cd9781d 100644 --- a/vcg/simplex/tetrahedron/component.h +++ b/vcg/simplex/tetrahedron/component.h @@ -47,7 +47,7 @@ public: //Empty vertexref inline typename T::VertexType * & V( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * const & V( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } - inline const typename T::VertexType * cV( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } + inline const typename T::VertexType * cV( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::CoordType & P( const int ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType & P( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType &cP( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } @@ -112,6 +112,7 @@ public: typename T::TetraPointer const cTTp( const int ) const { static typename T::TetraPointer const tp=0; assert(0); return tp; } char & VTi( const int ) { static char z=0; assert(0); return z; } + char VTi( const int ) const { static char z=0; assert(0); return z; } char cVTi( const int ) const { static char z=0; assert(0); return z; } char & TTi( const int ) { static char z=0; assert(0); return z; } char cTTi( const int ) const { static char z=0; assert(0); return z; } diff --git a/vcg/simplex/vertex/component.h b/vcg/simplex/vertex/component.h index 1a95aca9..1914dbbd 100644 --- a/vcg/simplex/vertex/component.h +++ b/vcg/simplex/vertex/component.h @@ -99,6 +99,7 @@ public: typename TT::TetraPointer &VTp() { static typename TT::TetraPointer tp = 0; assert(0); return tp; } typename TT::TetraPointer cVTp() const { static typename TT::TetraPointer tp = 0; assert(0); return tp; } int &VTi() { static int z = 0; assert(0); return z; } + int VTi() const { static int z = 0; assert(0); return z; } int cVTi() const { static int z = 0; assert(0); return z; } static bool HasVTAdjacency() { return false; } bool IsVTInitialized() const {return static_cast(this)->cVTi()!=-1;} @@ -112,6 +113,7 @@ public: typename TT::FacePointer &VFp() { static typename TT::FacePointer fp=0; assert(0); return fp; } typename TT::FacePointer cVFp() const { static typename TT::FacePointer fp=0; assert(0); return fp; } int &VFi() { static int z=-1; assert(0); return z;} + int VFi() const { static int z=-1; assert(0); return z;} int cVFi() const { static int z=-1; assert(0); return z;} bool IsNull() const { return true; } static bool HasVFAdjacency() { return false; } @@ -126,6 +128,7 @@ public: typename TT::EdgePointer &VEp() { static typename TT::EdgePointer ep=0; assert(0); return ep; } typename TT::EdgePointer cVEp() const { static typename TT::EdgePointer ep=0; assert(0); return ep; } int &VEi() { static int z=-1; return z;} + int VEi() const { static int z=-1; return z;} int cVEi() const { static int z=-1; return z;} static bool HasVEAdjacency() { return false; } bool IsVEInitialized() const {return static_cast(this)->cVEi()!=-1;} @@ -138,6 +141,7 @@ public: typename TT::HEdgePointer &VHp() { static typename TT::HEdgePointer ep=0; assert(0); return ep; } typename TT::HEdgePointer cVHp() const { static typename TT::HEdgePointer ep=0; assert(0); return ep; } int &VHi() { static int z=0; return z;} + int VHi() const { static int z=0; return z;} int cVHi() const { static int z=0; return z;} static bool HasVHAdjacency() { return false; } @@ -531,6 +535,7 @@ public: typename T::EdgePointer &VEp() {return _ep; } typename T::EdgePointer cVEp() const {return _ep; } int &VEi() {return _zp; } + int VEi() const {return _zp; } int cVEi() const {return _zp; } template < class RightValueType> void ImportData(const RightValueType & rVert ) { T::ImportData( rVert); } @@ -559,6 +564,7 @@ Note that if you use this component it is expected that on the Face you use also typename T::FacePointer &VFp() { return _fp; } typename T::FacePointer cVFp() const { return _fp; } int &VFi() { return _zp; } + int VFi() const { return _zp; } int cVFi() const { return _zp; } bool IsNull() const { return _zp==-1;} template < class RightValueType> diff --git a/vcg/simplex/vertex/component_ocf.h b/vcg/simplex/vertex/component_ocf.h index 72b42fbd..35572cbc 100644 --- a/vcg/simplex/vertex/component_ocf.h +++ b/vcg/simplex/vertex/component_ocf.h @@ -285,6 +285,10 @@ public: assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp; } + int VFi() const { + assert((*this).Base().VFAdjacencyEnabled); + return (*this).Base().AV[(*this).Index()]._zp; + } int cVFi() const { if(! (*this).Base().VFAdjacencyEnabled ) return -1; return (*this).Base().AV[(*this).Index()]._zp; From 1144dfbae47f615bddd76b4397192da8ff1d8b78 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 14:35:48 +0200 Subject: [PATCH 002/140] using range for in MeshAppendConst --- vcg/complex/append.h | 146 +++++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 62 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 4ea8fd03..cd52a483 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -63,12 +63,12 @@ public: typedef typename ConstMeshRight::FaceType FaceRight; typedef typename ConstMeshRight::TetraType TetraRight; typedef typename ConstMeshRight::TetraPointer TetraPointerRight; - typedef typename ConstMeshRight::ConstTetraIterator TetraIteratorRight; + typedef typename ConstMeshRight::TetraIterator TetraIteratorRight; typedef typename ConstMeshRight::VertexPointer VertexPointerRight; - typedef typename ConstMeshRight::ConstVertexIterator VertexIteratorRight; - typedef typename ConstMeshRight::ConstEdgeIterator EdgeIteratorRight; - typedef typename ConstMeshRight::ConstHEdgeIterator HEdgeIteratorRight; - typedef typename ConstMeshRight::ConstFaceIterator FaceIteratorRight; + typedef typename ConstMeshRight::VertexIterator VertexIteratorRight; + typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight; + typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight; + typedef typename ConstMeshRight::FaceIterator FaceIteratorRight; typedef typename ConstMeshRight::FacePointer FacePointerRight; struct Remap{ @@ -514,11 +514,12 @@ static void MeshAppendConst( else vp=Allocator::AddVertices(ml,mr.vn); - for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) + for (auto v : mr.vert) + //for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) { - if(!(*vi).IsD() && (!selected || (*vi).IsS())) + if(!v.IsD() && (!selected || v.IsS())) { - size_t ind=Index(mr,*vi); + size_t ind=Index(mr,v); remap.vert[ind]=int(Index(ml,*vp)); ++vp; } @@ -530,9 +531,10 @@ static void MeshAppendConst( 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); + for (auto e : mr.edge) + //for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei) + if(!e.IsD() && (!selected || e.IsS())){ + size_t ind=Index(mr,e); remap.edge[ind]=int(Index(ml,*ep)); ++ep; } @@ -544,31 +546,34 @@ static void MeshAppendConst( 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); + for (auto f : mr.face) + //for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi) + if(!f.IsD() && (!selected || f.IsS())){ + size_t ind=Index(mr,f); 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); + for (auto he : mr.hedge) + //for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi) + if(!he.IsD() && (!selected || he.IsS())){ + size_t ind=Index(mr,he); assert(remap.hedge[ind]==Remap::InvalidIndex()); HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); - (*hp).ImportData(*(hi)); + (*hp).ImportData(he); 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); + for (auto t : mr.tetra) + //for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if (!t.IsD() && (!selected || t.IsS())) { + size_t idx = Index(mr, t); assert (remap.tetra[idx] == Remap::InvalidIndex()); TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); - (*tp).ImportData(*ti); + (*tp).ImportData(t); remap.tetra[idx] = Index(ml, *tp); } @@ -576,64 +581,69 @@ static void MeshAppendConst( // 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); + for (auto v: mr.vert) + //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi) + if( !v.IsD() && (!selected || v.IsS())){ + ml.vert[remap.vert[Index(mr,v)]].ImportData(v); + if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,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); + for (auto e: mr.edge) + //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei) + if(!e.IsD() && (!selected || e.IsS())){ + ml.edge[remap.edge[Index(mr,e)]].ImportData(e); // Edge to Vertex Adj - EdgeLeft &el = ml.edge[remap.edge[Index(mr,*ei)]]; + EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; 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))]]; + el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]]; + el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]]; } - if(adjFlag) ImportEdgeAdj(ml,mr,el,*ei,remap); + if(adjFlag) ImportEdgeAdj(ml,mr,el,e,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())) + for (auto f: mr.face) + //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi) + if(!f.IsD() && (!selected || f.IsS())) { - FaceLeft &fl = ml.face[remap.face[Index(mr,*fi)]]; - fl.Alloc(fi->VN()); + FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; + fl.Alloc(f.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.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; } - fl.ImportData(*fi); + fl.ImportData(f); 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); + if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,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); + for (auto he : mr.hedge) + //for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) + if(!he.IsD() && (!selected || he.IsS())){ + ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); + ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); } //tetra - for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if(!(*ti).IsD() && (!selected || (*ti).IsS())) + for (auto t: mr.tetra) + //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if(!t.IsD() && (!selected || t.IsS())) { - TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,*ti)]]; + TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; 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.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]]; } - tl.ImportData(*ti); - if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,*ti)]], *ti, remap); + tl.ImportData(t); + if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); } @@ -659,9 +669,12 @@ static void MeshAppendConst( 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); + for (auto v: mr.vert){ + //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) + if( !v.IsD() && (!selected || v.IsS())) + (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); + ++id_r; + } } } @@ -671,9 +684,12 @@ static void MeshAppendConst( 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); + for (auto e: mr.edge){ + //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) + if( !e.IsD() && (!selected || e.IsS())) + (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); + ++id_r; + } } } @@ -683,9 +699,12 @@ static void MeshAppendConst( 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); + for (auto f: mr.face) { + //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) + if( !f.IsD() && (!selected || f.IsS())) + (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); + ++id_r; + } } } @@ -695,9 +714,12 @@ static void MeshAppendConst( 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); + for (auto t: mr.tetra) { + //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r) + if( !t.IsD() && (!selected || t.IsS())) + (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); + ++id_r; + } } } // per mesh attributes From 6014f75b60815657dc6ac014dd6aca8d4e6ff6fc Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 15:44:27 +0200 Subject: [PATCH 003/140] using ForEach. add const ForEach and ForEachHEdge --- vcg/complex/append.h | 223 ++++++++++++++++++++++-------------------- vcg/complex/foreach.h | 102 +++++++++++++++++++ 2 files changed, 217 insertions(+), 108 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index cd52a483..02580a4b 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -514,16 +514,15 @@ static void MeshAppendConst( else vp=Allocator::AddVertices(ml,mr.vn); - for (auto v : mr.vert) - //for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) + ForEachVertex(mr, [&](const VertexRight& v) { - if(!v.IsD() && (!selected || v.IsS())) + if(!selected || v.IsS()) { size_t ind=Index(mr,v); remap.vert[ind]=int(Index(ml,*vp)); ++vp; } - } + }); // edge remap.edge.resize(mr.edge.size(), Remap::InvalidIndex()); EdgeIteratorLeft ep; @@ -531,13 +530,14 @@ static void MeshAppendConst( if(selected) ep=Allocator::AddEdges(ml,sen); else ep=Allocator::AddEdges(ml,mr.en); - for (auto e : mr.edge) - //for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei) - if(!e.IsD() && (!selected || e.IsS())){ + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ size_t ind=Index(mr,e); remap.edge[ind]=int(Index(ml,*ep)); ++ep; } + }); // face remap.face.resize(mr.face.size(), Remap::InvalidIndex()); @@ -546,52 +546,58 @@ static void MeshAppendConst( if(selected) fp=Allocator::AddFaces(ml,sfn); else fp=Allocator::AddFaces(ml,mr.fn); - for (auto f : mr.face) - //for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi) - if(!f.IsD() && (!selected || f.IsS())){ + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()){ size_t ind=Index(mr,f); remap.face[ind]=int(Index(ml,*fp)); ++fp; } + }); // hedge remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); - for (auto he : mr.hedge) - //for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi) - if(!he.IsD() && (!selected || he.IsS())){ + + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ size_t ind=Index(mr,he); assert(remap.hedge[ind]==Remap::InvalidIndex()); HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); (*hp).ImportData(he); remap.hedge[ind]=Index(ml,*hp); } + }); remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); - for (auto t : mr.tetra) - //for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if (!t.IsD() && (!selected || t.IsS())) { + + ForEachTetra(mr, [&](const TetraRight& t) + { + if (!selected || t.IsS()) { size_t idx = Index(mr, t); assert (remap.tetra[idx] == Remap::InvalidIndex()); TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); (*tp).ImportData(t); remap.tetra[idx] = Index(ml, *tp); } + }); // phase 2. // copy data from mr to its corresponding elements in ml and adjacencies // vertex - for (auto v: mr.vert) - //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi) - if( !v.IsD() && (!selected || v.IsS())){ + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()){ ml.vert[remap.vert[Index(mr,v)]].ImportData(v); if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,remap); } + }); // edge - for (auto e: mr.edge) - //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei) - if(!e.IsD() && (!selected || e.IsS())){ + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ ml.edge[remap.edge[Index(mr,e)]].ImportData(e); // Edge to Vertex Adj EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; @@ -601,13 +607,14 @@ static void MeshAppendConst( } if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap); } + }); // face const size_t textureOffset = ml.textures.size(); bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0); - for (auto f: mr.face) - //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi) - if(!f.IsD() && (!selected || f.IsS())) + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()) { FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; fl.Alloc(f.VN()); @@ -622,19 +629,21 @@ static void MeshAppendConst( if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap); } + }); // hedge - for (auto he : mr.hedge) - //for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) - if(!he.IsD() && (!selected || he.IsS())){ + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); } + }); //tetra - for (auto t: mr.tetra) - //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if(!t.IsD() && (!selected || t.IsS())) + ForEachTetra(mr, [&](const TetraRight& t) + { + if(!selected || t.IsS()) { TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; @@ -646,91 +655,89 @@ static void MeshAppendConst( if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); } + }); - // phase 3. - // take care of other per mesh data: textures, attributes + // 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()); + // 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 + // 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< PointerToAttribute >::iterator al, ar; + unsigned int id_r; + typename std::set< PointerToAttribute >::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 (auto v: mr.vert){ - //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) - if( !v.IsD() && (!selected || v.IsS())) - (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (auto v: mr.vert){ + if( !v.IsD() && (!selected || v.IsS())) + (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto e: mr.edge){ - //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) - if( !e.IsD() && (!selected || e.IsS())) - (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (auto e: mr.edge){ + if( !e.IsD() && (!selected || e.IsS())) + (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto f: mr.face) { - //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) - if( !f.IsD() && (!selected || f.IsS())) - (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (auto f: mr.face) { + if( !f.IsD() && (!selected || f.IsS())) + (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto t: mr.tetra) { - //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r) - if( !t.IsD() && (!selected || t.IsS())) - (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); - ++id_r; - } - } - } - // 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()) - // //... - // } + // 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 (auto t: mr.tetra) { + if( !t.IsD() && (!selected || t.IsS())) + (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); + ++id_r; + } + } + } + + // 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 Copy the second mesh over the first one. diff --git a/vcg/complex/foreach.h b/vcg/complex/foreach.h index 156d3489..4f7710fd 100644 --- a/vcg/complex/foreach.h +++ b/vcg/complex/foreach.h @@ -34,6 +34,22 @@ namespace tri { @{ */ +template +inline void ForEachFacePos(const MeshType &m, std::function &)> action) +{ + typedef typename face::Pos PosType; + + for(auto fi=m.face.begin();fi!=m.face.end();++fi) + if(!(*fi).IsD()) + { + for(int i=0;i<3;++i) + { + PosType pi(&*fi,i); + action(pi); + } + } +} + template inline void ForEachFacePos(MeshType &m, std::function &)> action) { @@ -108,6 +124,25 @@ inline void ForEachFace(MeshType &m, std::function +inline void ForEachVertex(const MeshType &m, std::function action) +{ + if(m.vn == (int) m.vert.size()) + { + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) { + action(*vi); + } + } + else + { + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) + if(!(*vi).IsD()) + { + action(*vi); + } + } +} + template inline void ForEachVertex(MeshType &m, std::function action) { @@ -127,6 +162,54 @@ inline void ForEachVertex(MeshType &m, std::function +inline void ForEachHEdge(const MeshType &m, std::function action) +{ + if(m.hn == (int) m.hedge.size()) + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) { + action(*hei); + } + } + else + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) + if(!(*hei).IsD()) + { + action(*hei); + } + } +} + +template +inline void ForEachHEdge(MeshType &m, std::function action) +{ + if(m.hn == (int) m.hedge.size()) + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) { + action(*hei); + } + } + else + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) + if(!(*hei).IsD()) + { + action(*hei); + } + } +} + /** * ForEachEdge Helper * to traverse all the vertexes of a mesh you can simply write something like: @@ -137,6 +220,25 @@ inline void ForEachVertex(MeshType &m, std::function +inline void ForEachEdge(const MeshType &m, std::function action) +{ + if(m.en == (int) m.edge.size()) + { + for(auto ei=m.edge.begin();ei!=m.edge.end();++ei) { + action(*ei); + } + } + else + { + for(auto ei=m.edge.begin();ei!=m.edge.end();++ei) + if(!(*ei).IsD()) + { + action(*ei); + } + } +} + template inline void ForEachEdge(MeshType &m, std::function action) { From 27856fce257cabe19f720d341a8b490b627abbd5 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 16:38:22 +0200 Subject: [PATCH 004/140] clean selection.h --- vcg/complex/algorithms/update/selection.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index b6cd1c5f..30cc5a8f 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -272,8 +272,6 @@ static void Clear(MeshType &m) static size_t FaceCount(const MeshType &m) { size_t selCnt=0; - //for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) - // if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; for (auto f: m.face) if(!f.IsD() && f.IsS()) ++selCnt; return selCnt; @@ -283,8 +281,6 @@ static size_t FaceCount(const MeshType &m) static size_t EdgeCount(const MeshType &m) { size_t selCnt=0; - //for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) - // if(!(*ei).IsD() && (*ei).IsS()) ++selCnt; for (auto e: m.edge) if(!e.IsD() && e.IsS()) ++selCnt; return selCnt; @@ -294,8 +290,6 @@ static size_t EdgeCount(const MeshType &m) static size_t VertexCount(const MeshType &m) { size_t selCnt=0; - //for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) - // if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; for (auto v: m.vert) if(!v.IsD() && v.IsS()) ++selCnt; return selCnt; @@ -305,7 +299,7 @@ static size_t VertexCount(const MeshType &m) static size_t TetraCount (const MeshType & m) { size_t selCnt = 0; - ForEachTetra(m, [&selCnt] (TetraType & t) { + ForEachTetra(m, [&selCnt] (const TetraType & t) { if (t.IsS()) ++selCnt; }); From 98ff47110d81c78fef0a3fa810ddfa4f44940549 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 14:06:10 +0200 Subject: [PATCH 005/140] const correctness for make a copy from a const right Mesh --- vcg/complex/algorithms/update/selection.h | 26 ++- vcg/complex/append.h | 262 +++++++++++++++++++++- vcg/simplex/edge/component.h | 2 + vcg/simplex/face/component.h | 1 + vcg/simplex/face/component_ocf.h | 5 + vcg/simplex/face/component_polygon.h | 1 + vcg/simplex/tetrahedron/component.h | 3 +- vcg/simplex/vertex/component.h | 6 + vcg/simplex/vertex/component_ocf.h | 4 + 9 files changed, 289 insertions(+), 21 deletions(-) diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index ae9d4d04..b6cd1c5f 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -269,34 +269,40 @@ static void Clear(MeshType &m) } /// \brief This function returns the number of selected faces. -static size_t FaceCount(MeshType &m) +static size_t FaceCount(const MeshType &m) { size_t selCnt=0; - for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) - if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; + //for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) + // if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; + for (auto f: m.face) + if(!f.IsD() && f.IsS()) ++selCnt; return selCnt; } /// \brief This function returns the number of selected edges. -static size_t EdgeCount(MeshType &m) +static size_t EdgeCount(const MeshType &m) { size_t selCnt=0; - for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) - if(!(*ei).IsD() && (*ei).IsS()) ++selCnt; + //for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) + // if(!(*ei).IsD() && (*ei).IsS()) ++selCnt; + for (auto e: m.edge) + if(!e.IsD() && e.IsS()) ++selCnt; return selCnt; } /// \brief This function returns the number of selected vertices. -static size_t VertexCount(MeshType &m) +static size_t VertexCount(const MeshType &m) { size_t selCnt=0; - for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) - if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; + //for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) + // if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; + for (auto v: m.vert) + if(!v.IsD() && v.IsS()) ++selCnt; return selCnt; } /// \brief This function returns the number of selected tetras. -static size_t TetraCount (MeshType & m) +static size_t TetraCount (const MeshType & m) { size_t selCnt = 0; ForEachTetra(m, [&selCnt] (TetraType & t) { diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 047214f9..4ea8fd03 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -63,12 +63,12 @@ public: typedef typename ConstMeshRight::FaceType FaceRight; typedef typename ConstMeshRight::TetraType TetraRight; typedef typename ConstMeshRight::TetraPointer TetraPointerRight; - typedef typename ConstMeshRight::TetraIterator TetraIteratorRight; + typedef typename ConstMeshRight::ConstTetraIterator TetraIteratorRight; typedef typename ConstMeshRight::VertexPointer VertexPointerRight; - typedef typename ConstMeshRight::VertexIterator VertexIteratorRight; - typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight; - typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight; - typedef typename ConstMeshRight::FaceIterator FaceIteratorRight; + typedef typename ConstMeshRight::ConstVertexIterator VertexIteratorRight; + typedef typename ConstMeshRight::ConstEdgeIterator EdgeIteratorRight; + typedef typename ConstMeshRight::ConstHEdgeIterator HEdgeIteratorRight; + typedef typename ConstMeshRight::ConstFaceIterator FaceIteratorRight; typedef typename ConstMeshRight::FacePointer FacePointerRight; struct Remap{ @@ -76,7 +76,7 @@ public: std::vector vert, face, edge, hedge, tetra; }; - static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){ + static void ImportVertexAdj(MeshLeft &ml, const ConstMeshRight &mr, VertexLeft &vl, const VertexRight &vr, Remap &remap ){ // Vertex to Edge Adj if(HasVEAdjacency(ml) && HasVEAdjacency(mr) && vr.cVEp() != 0){ size_t i = Index(mr,vr.cVEp()); @@ -105,7 +105,7 @@ public: } } - static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) + static void ImportEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) { // Edge to Edge Adj if(HasEEAdjacency(ml) && HasEEAdjacency(mr)) @@ -129,7 +129,7 @@ public: } - static void ImportFaceAdj(MeshLeft &ml, ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap ) + static void ImportFaceAdj(MeshLeft &ml, const ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap ) { // Face to Edge Adj if(HasFEAdjacency(ml) && HasFEAdjacency(mr)){ @@ -183,7 +183,7 @@ public: fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]]; } - static void ImportHEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){ + static void ImportHEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){ // HEdge to Vertex Adj if(HasHVAdjacency(ml) && HasHVAdjacency(mr)) hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]]; @@ -214,7 +214,7 @@ public: hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]]; } - static void ImportTetraAdj(MeshLeft &ml, ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap ) + static void ImportTetraAdj(MeshLeft &ml, const ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap ) { // Tetra to Tetra Adj if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){ @@ -476,6 +476,241 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, // } } +/** + * @brief MeshAppendConst + * @param ml + * @param mr + * + * This is function is similar with the Mesh function, but does not + * never update selections. In some cases, after the append, + * selection of vertices may be inconsistent with face selection, + * as explained above. + * To avoid this, before using this function, call the following functions: + * + * \code{.cpp} + * vcg::tri::UpdateSelection::VertexFromEdgeLoose(mr,true); + * vcg::tri::UpdateSelection::VertexFromFaceLoose(mr,true); + * \endcode + * + * or, use the Mesh function that takes a non-const Right Mesh argument. + */ +static void MeshAppendConst( + MeshLeft& ml, + const ConstMeshRight& mr, + const bool selected = false, + const bool adjFlag = 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(), 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< PointerToAttribute >::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 Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected elements are copied. */ @@ -485,6 +720,13 @@ static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, cons Mesh(ml,mr,selected,adjFlag); ml.bbox.Import(mr.bbox); } + +static void MeshCopyConst(MeshLeft& ml, const ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) +{ + ml.Clear(); + MeshAppendConst(ml,mr,selected,adjFlag); + ml.bbox.Import(mr.bbox); +} /*! \brief %Append only the selected elements of second mesh to the first one. It is just a wrap of the main Append::Mesh() diff --git a/vcg/simplex/edge/component.h b/vcg/simplex/edge/component.h index a78ca4c6..69d32765 100644 --- a/vcg/simplex/edge/component.h +++ b/vcg/simplex/edge/component.h @@ -78,6 +78,7 @@ public: typename T::EdgePointer &VEp(const int & ) { static typename T::EdgePointer ep=0; assert(0); return ep; } typename T::EdgePointer cVEp(const int & ) const { static typename T::EdgePointer ep=0; assert(0); return ep; } int &VEi(const int &){static int z=0; assert(0); return z;} + int VEi(const int &) const {static int z=0; assert(0); return z;} int cVEi(const int &) const {static int z=0; assert(0); return z;} static bool HasVEAdjacency() { return false; } @@ -278,6 +279,7 @@ public: typename T::EdgePointer &VEp(const int & i) {return _ep[i]; } typename T::EdgePointer cVEp(const int & i) const {return _ep[i]; } int &VEi(const int & i){ return _zp[i];} + int VEi(const int & i)const {return _zp[i];} int cVEi(const int &i )const {return _zp[i];} template < class LeftV> diff --git a/vcg/simplex/face/component.h b/vcg/simplex/face/component.h index ebdc3739..da731066 100644 --- a/vcg/simplex/face/component.h +++ b/vcg/simplex/face/component.h @@ -114,6 +114,7 @@ public: typename T::HEdgePointer &FHp() { static typename T::HEdgePointer fp=0; assert(0); return fp; } typename T::HEdgePointer cFHp() const { static typename T::HEdgePointer fp=0; assert(0); return fp; } char &VFi(int) { static char z=0; assert(0); return z;} + char VFi(int) const { static char z=0; assert(0); return z;} char &FFi(int) { static char z=0; assert(0); return z;} char cVFi(int) const { static char z=0; assert(0); return z;} char cFFi(int) const { static char z=0; assert(0); return z;} diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index bf4c3fb1..a09e84f7 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -408,6 +408,11 @@ public: return (*this).Base().AV[(*this).Index()]._zp[j]; } + char VFi(const int j) const { + assert((*this).Base().VFAdjacencyEnabled); + return (*this).Base().AV[(*this).Index()]._zp[j]; + } + char cVFi(const int j) const { assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp[j]; diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index dde27016..8ac67f47 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -136,6 +136,7 @@ public: typename T::FacePointer const VFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } typename T::FacePointer const cVFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } char &VFi(const int j) {return _vfiP[j]; } + char VFi(const int j) const {return _vfiP[j]; } template void ImportData(const LeftF & leftF){T::ImportData(leftF);} inline void Alloc(const int & ns) { diff --git a/vcg/simplex/tetrahedron/component.h b/vcg/simplex/tetrahedron/component.h index d2d8c878..7cd9781d 100644 --- a/vcg/simplex/tetrahedron/component.h +++ b/vcg/simplex/tetrahedron/component.h @@ -47,7 +47,7 @@ public: //Empty vertexref inline typename T::VertexType * & V( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * const & V( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } - inline const typename T::VertexType * cV( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } + inline const typename T::VertexType * cV( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::CoordType & P( const int ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType & P( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType &cP( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } @@ -112,6 +112,7 @@ public: typename T::TetraPointer const cTTp( const int ) const { static typename T::TetraPointer const tp=0; assert(0); return tp; } char & VTi( const int ) { static char z=0; assert(0); return z; } + char VTi( const int ) const { static char z=0; assert(0); return z; } char cVTi( const int ) const { static char z=0; assert(0); return z; } char & TTi( const int ) { static char z=0; assert(0); return z; } char cTTi( const int ) const { static char z=0; assert(0); return z; } diff --git a/vcg/simplex/vertex/component.h b/vcg/simplex/vertex/component.h index 1a95aca9..1914dbbd 100644 --- a/vcg/simplex/vertex/component.h +++ b/vcg/simplex/vertex/component.h @@ -99,6 +99,7 @@ public: typename TT::TetraPointer &VTp() { static typename TT::TetraPointer tp = 0; assert(0); return tp; } typename TT::TetraPointer cVTp() const { static typename TT::TetraPointer tp = 0; assert(0); return tp; } int &VTi() { static int z = 0; assert(0); return z; } + int VTi() const { static int z = 0; assert(0); return z; } int cVTi() const { static int z = 0; assert(0); return z; } static bool HasVTAdjacency() { return false; } bool IsVTInitialized() const {return static_cast(this)->cVTi()!=-1;} @@ -112,6 +113,7 @@ public: typename TT::FacePointer &VFp() { static typename TT::FacePointer fp=0; assert(0); return fp; } typename TT::FacePointer cVFp() const { static typename TT::FacePointer fp=0; assert(0); return fp; } int &VFi() { static int z=-1; assert(0); return z;} + int VFi() const { static int z=-1; assert(0); return z;} int cVFi() const { static int z=-1; assert(0); return z;} bool IsNull() const { return true; } static bool HasVFAdjacency() { return false; } @@ -126,6 +128,7 @@ public: typename TT::EdgePointer &VEp() { static typename TT::EdgePointer ep=0; assert(0); return ep; } typename TT::EdgePointer cVEp() const { static typename TT::EdgePointer ep=0; assert(0); return ep; } int &VEi() { static int z=-1; return z;} + int VEi() const { static int z=-1; return z;} int cVEi() const { static int z=-1; return z;} static bool HasVEAdjacency() { return false; } bool IsVEInitialized() const {return static_cast(this)->cVEi()!=-1;} @@ -138,6 +141,7 @@ public: typename TT::HEdgePointer &VHp() { static typename TT::HEdgePointer ep=0; assert(0); return ep; } typename TT::HEdgePointer cVHp() const { static typename TT::HEdgePointer ep=0; assert(0); return ep; } int &VHi() { static int z=0; return z;} + int VHi() const { static int z=0; return z;} int cVHi() const { static int z=0; return z;} static bool HasVHAdjacency() { return false; } @@ -531,6 +535,7 @@ public: typename T::EdgePointer &VEp() {return _ep; } typename T::EdgePointer cVEp() const {return _ep; } int &VEi() {return _zp; } + int VEi() const {return _zp; } int cVEi() const {return _zp; } template < class RightValueType> void ImportData(const RightValueType & rVert ) { T::ImportData( rVert); } @@ -559,6 +564,7 @@ Note that if you use this component it is expected that on the Face you use also typename T::FacePointer &VFp() { return _fp; } typename T::FacePointer cVFp() const { return _fp; } int &VFi() { return _zp; } + int VFi() const { return _zp; } int cVFi() const { return _zp; } bool IsNull() const { return _zp==-1;} template < class RightValueType> diff --git a/vcg/simplex/vertex/component_ocf.h b/vcg/simplex/vertex/component_ocf.h index 72b42fbd..35572cbc 100644 --- a/vcg/simplex/vertex/component_ocf.h +++ b/vcg/simplex/vertex/component_ocf.h @@ -285,6 +285,10 @@ public: assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp; } + int VFi() const { + assert((*this).Base().VFAdjacencyEnabled); + return (*this).Base().AV[(*this).Index()]._zp; + } int cVFi() const { if(! (*this).Base().VFAdjacencyEnabled ) return -1; return (*this).Base().AV[(*this).Index()]._zp; From dc5b0649eeb08e924b0654deeba92be019096ba5 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 14:35:48 +0200 Subject: [PATCH 006/140] using range for in MeshAppendConst --- vcg/complex/append.h | 146 +++++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 62 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 4ea8fd03..cd52a483 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -63,12 +63,12 @@ public: typedef typename ConstMeshRight::FaceType FaceRight; typedef typename ConstMeshRight::TetraType TetraRight; typedef typename ConstMeshRight::TetraPointer TetraPointerRight; - typedef typename ConstMeshRight::ConstTetraIterator TetraIteratorRight; + typedef typename ConstMeshRight::TetraIterator TetraIteratorRight; typedef typename ConstMeshRight::VertexPointer VertexPointerRight; - typedef typename ConstMeshRight::ConstVertexIterator VertexIteratorRight; - typedef typename ConstMeshRight::ConstEdgeIterator EdgeIteratorRight; - typedef typename ConstMeshRight::ConstHEdgeIterator HEdgeIteratorRight; - typedef typename ConstMeshRight::ConstFaceIterator FaceIteratorRight; + typedef typename ConstMeshRight::VertexIterator VertexIteratorRight; + typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight; + typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight; + typedef typename ConstMeshRight::FaceIterator FaceIteratorRight; typedef typename ConstMeshRight::FacePointer FacePointerRight; struct Remap{ @@ -514,11 +514,12 @@ static void MeshAppendConst( else vp=Allocator::AddVertices(ml,mr.vn); - for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) + for (auto v : mr.vert) + //for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) { - if(!(*vi).IsD() && (!selected || (*vi).IsS())) + if(!v.IsD() && (!selected || v.IsS())) { - size_t ind=Index(mr,*vi); + size_t ind=Index(mr,v); remap.vert[ind]=int(Index(ml,*vp)); ++vp; } @@ -530,9 +531,10 @@ static void MeshAppendConst( 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); + for (auto e : mr.edge) + //for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei) + if(!e.IsD() && (!selected || e.IsS())){ + size_t ind=Index(mr,e); remap.edge[ind]=int(Index(ml,*ep)); ++ep; } @@ -544,31 +546,34 @@ static void MeshAppendConst( 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); + for (auto f : mr.face) + //for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi) + if(!f.IsD() && (!selected || f.IsS())){ + size_t ind=Index(mr,f); 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); + for (auto he : mr.hedge) + //for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi) + if(!he.IsD() && (!selected || he.IsS())){ + size_t ind=Index(mr,he); assert(remap.hedge[ind]==Remap::InvalidIndex()); HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); - (*hp).ImportData(*(hi)); + (*hp).ImportData(he); 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); + for (auto t : mr.tetra) + //for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if (!t.IsD() && (!selected || t.IsS())) { + size_t idx = Index(mr, t); assert (remap.tetra[idx] == Remap::InvalidIndex()); TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); - (*tp).ImportData(*ti); + (*tp).ImportData(t); remap.tetra[idx] = Index(ml, *tp); } @@ -576,64 +581,69 @@ static void MeshAppendConst( // 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); + for (auto v: mr.vert) + //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi) + if( !v.IsD() && (!selected || v.IsS())){ + ml.vert[remap.vert[Index(mr,v)]].ImportData(v); + if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,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); + for (auto e: mr.edge) + //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei) + if(!e.IsD() && (!selected || e.IsS())){ + ml.edge[remap.edge[Index(mr,e)]].ImportData(e); // Edge to Vertex Adj - EdgeLeft &el = ml.edge[remap.edge[Index(mr,*ei)]]; + EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; 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))]]; + el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]]; + el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]]; } - if(adjFlag) ImportEdgeAdj(ml,mr,el,*ei,remap); + if(adjFlag) ImportEdgeAdj(ml,mr,el,e,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())) + for (auto f: mr.face) + //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi) + if(!f.IsD() && (!selected || f.IsS())) { - FaceLeft &fl = ml.face[remap.face[Index(mr,*fi)]]; - fl.Alloc(fi->VN()); + FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; + fl.Alloc(f.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.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; } - fl.ImportData(*fi); + fl.ImportData(f); 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); + if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,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); + for (auto he : mr.hedge) + //for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) + if(!he.IsD() && (!selected || he.IsS())){ + ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); + ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); } //tetra - for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if(!(*ti).IsD() && (!selected || (*ti).IsS())) + for (auto t: mr.tetra) + //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if(!t.IsD() && (!selected || t.IsS())) { - TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,*ti)]]; + TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; 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.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]]; } - tl.ImportData(*ti); - if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,*ti)]], *ti, remap); + tl.ImportData(t); + if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); } @@ -659,9 +669,12 @@ static void MeshAppendConst( 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); + for (auto v: mr.vert){ + //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) + if( !v.IsD() && (!selected || v.IsS())) + (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); + ++id_r; + } } } @@ -671,9 +684,12 @@ static void MeshAppendConst( 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); + for (auto e: mr.edge){ + //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) + if( !e.IsD() && (!selected || e.IsS())) + (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); + ++id_r; + } } } @@ -683,9 +699,12 @@ static void MeshAppendConst( 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); + for (auto f: mr.face) { + //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) + if( !f.IsD() && (!selected || f.IsS())) + (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); + ++id_r; + } } } @@ -695,9 +714,12 @@ static void MeshAppendConst( 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); + for (auto t: mr.tetra) { + //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r) + if( !t.IsD() && (!selected || t.IsS())) + (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); + ++id_r; + } } } // per mesh attributes From 09b12339c04efce4f80fcf24024c325ae4b5aa25 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 15:44:27 +0200 Subject: [PATCH 007/140] using ForEach. add const ForEach and ForEachHEdge --- vcg/complex/append.h | 223 ++++++++++++++++++++++-------------------- vcg/complex/foreach.h | 102 +++++++++++++++++++ 2 files changed, 217 insertions(+), 108 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index cd52a483..02580a4b 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -514,16 +514,15 @@ static void MeshAppendConst( else vp=Allocator::AddVertices(ml,mr.vn); - for (auto v : mr.vert) - //for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) + ForEachVertex(mr, [&](const VertexRight& v) { - if(!v.IsD() && (!selected || v.IsS())) + if(!selected || v.IsS()) { size_t ind=Index(mr,v); remap.vert[ind]=int(Index(ml,*vp)); ++vp; } - } + }); // edge remap.edge.resize(mr.edge.size(), Remap::InvalidIndex()); EdgeIteratorLeft ep; @@ -531,13 +530,14 @@ static void MeshAppendConst( if(selected) ep=Allocator::AddEdges(ml,sen); else ep=Allocator::AddEdges(ml,mr.en); - for (auto e : mr.edge) - //for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei) - if(!e.IsD() && (!selected || e.IsS())){ + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ size_t ind=Index(mr,e); remap.edge[ind]=int(Index(ml,*ep)); ++ep; } + }); // face remap.face.resize(mr.face.size(), Remap::InvalidIndex()); @@ -546,52 +546,58 @@ static void MeshAppendConst( if(selected) fp=Allocator::AddFaces(ml,sfn); else fp=Allocator::AddFaces(ml,mr.fn); - for (auto f : mr.face) - //for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi) - if(!f.IsD() && (!selected || f.IsS())){ + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()){ size_t ind=Index(mr,f); remap.face[ind]=int(Index(ml,*fp)); ++fp; } + }); // hedge remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); - for (auto he : mr.hedge) - //for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi) - if(!he.IsD() && (!selected || he.IsS())){ + + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ size_t ind=Index(mr,he); assert(remap.hedge[ind]==Remap::InvalidIndex()); HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); (*hp).ImportData(he); remap.hedge[ind]=Index(ml,*hp); } + }); remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); - for (auto t : mr.tetra) - //for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if (!t.IsD() && (!selected || t.IsS())) { + + ForEachTetra(mr, [&](const TetraRight& t) + { + if (!selected || t.IsS()) { size_t idx = Index(mr, t); assert (remap.tetra[idx] == Remap::InvalidIndex()); TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); (*tp).ImportData(t); remap.tetra[idx] = Index(ml, *tp); } + }); // phase 2. // copy data from mr to its corresponding elements in ml and adjacencies // vertex - for (auto v: mr.vert) - //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi) - if( !v.IsD() && (!selected || v.IsS())){ + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()){ ml.vert[remap.vert[Index(mr,v)]].ImportData(v); if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,remap); } + }); // edge - for (auto e: mr.edge) - //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei) - if(!e.IsD() && (!selected || e.IsS())){ + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ ml.edge[remap.edge[Index(mr,e)]].ImportData(e); // Edge to Vertex Adj EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; @@ -601,13 +607,14 @@ static void MeshAppendConst( } if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap); } + }); // face const size_t textureOffset = ml.textures.size(); bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0); - for (auto f: mr.face) - //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi) - if(!f.IsD() && (!selected || f.IsS())) + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()) { FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; fl.Alloc(f.VN()); @@ -622,19 +629,21 @@ static void MeshAppendConst( if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap); } + }); // hedge - for (auto he : mr.hedge) - //for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) - if(!he.IsD() && (!selected || he.IsS())){ + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); } + }); //tetra - for (auto t: mr.tetra) - //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if(!t.IsD() && (!selected || t.IsS())) + ForEachTetra(mr, [&](const TetraRight& t) + { + if(!selected || t.IsS()) { TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; @@ -646,91 +655,89 @@ static void MeshAppendConst( if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); } + }); - // phase 3. - // take care of other per mesh data: textures, attributes + // 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()); + // 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 + // 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< PointerToAttribute >::iterator al, ar; + unsigned int id_r; + typename std::set< PointerToAttribute >::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 (auto v: mr.vert){ - //for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) - if( !v.IsD() && (!selected || v.IsS())) - (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (auto v: mr.vert){ + if( !v.IsD() && (!selected || v.IsS())) + (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto e: mr.edge){ - //for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) - if( !e.IsD() && (!selected || e.IsS())) - (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (auto e: mr.edge){ + if( !e.IsD() && (!selected || e.IsS())) + (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto f: mr.face) { - //for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) - if( !f.IsD() && (!selected || f.IsS())) - (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (auto f: mr.face) { + if( !f.IsD() && (!selected || f.IsS())) + (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto t: mr.tetra) { - //for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r) - if( !t.IsD() && (!selected || t.IsS())) - (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); - ++id_r; - } - } - } - // 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()) - // //... - // } + // 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 (auto t: mr.tetra) { + if( !t.IsD() && (!selected || t.IsS())) + (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); + ++id_r; + } + } + } + + // 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 Copy the second mesh over the first one. diff --git a/vcg/complex/foreach.h b/vcg/complex/foreach.h index 156d3489..4f7710fd 100644 --- a/vcg/complex/foreach.h +++ b/vcg/complex/foreach.h @@ -34,6 +34,22 @@ namespace tri { @{ */ +template +inline void ForEachFacePos(const MeshType &m, std::function &)> action) +{ + typedef typename face::Pos PosType; + + for(auto fi=m.face.begin();fi!=m.face.end();++fi) + if(!(*fi).IsD()) + { + for(int i=0;i<3;++i) + { + PosType pi(&*fi,i); + action(pi); + } + } +} + template inline void ForEachFacePos(MeshType &m, std::function &)> action) { @@ -108,6 +124,25 @@ inline void ForEachFace(MeshType &m, std::function +inline void ForEachVertex(const MeshType &m, std::function action) +{ + if(m.vn == (int) m.vert.size()) + { + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) { + action(*vi); + } + } + else + { + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) + if(!(*vi).IsD()) + { + action(*vi); + } + } +} + template inline void ForEachVertex(MeshType &m, std::function action) { @@ -127,6 +162,54 @@ inline void ForEachVertex(MeshType &m, std::function +inline void ForEachHEdge(const MeshType &m, std::function action) +{ + if(m.hn == (int) m.hedge.size()) + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) { + action(*hei); + } + } + else + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) + if(!(*hei).IsD()) + { + action(*hei); + } + } +} + +template +inline void ForEachHEdge(MeshType &m, std::function action) +{ + if(m.hn == (int) m.hedge.size()) + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) { + action(*hei); + } + } + else + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) + if(!(*hei).IsD()) + { + action(*hei); + } + } +} + /** * ForEachEdge Helper * to traverse all the vertexes of a mesh you can simply write something like: @@ -137,6 +220,25 @@ inline void ForEachVertex(MeshType &m, std::function +inline void ForEachEdge(const MeshType &m, std::function action) +{ + if(m.en == (int) m.edge.size()) + { + for(auto ei=m.edge.begin();ei!=m.edge.end();++ei) { + action(*ei); + } + } + else + { + for(auto ei=m.edge.begin();ei!=m.edge.end();++ei) + if(!(*ei).IsD()) + { + action(*ei); + } + } +} + template inline void ForEachEdge(MeshType &m, std::function action) { From 8874b3785823c027744fd9d2441069e9f45c2119 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 10 Sep 2020 16:38:22 +0200 Subject: [PATCH 008/140] clean selection.h --- vcg/complex/algorithms/update/selection.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index b6cd1c5f..30cc5a8f 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -272,8 +272,6 @@ static void Clear(MeshType &m) static size_t FaceCount(const MeshType &m) { size_t selCnt=0; - //for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) - // if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; for (auto f: m.face) if(!f.IsD() && f.IsS()) ++selCnt; return selCnt; @@ -283,8 +281,6 @@ static size_t FaceCount(const MeshType &m) static size_t EdgeCount(const MeshType &m) { size_t selCnt=0; - //for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) - // if(!(*ei).IsD() && (*ei).IsS()) ++selCnt; for (auto e: m.edge) if(!e.IsD() && e.IsS()) ++selCnt; return selCnt; @@ -294,8 +290,6 @@ static size_t EdgeCount(const MeshType &m) static size_t VertexCount(const MeshType &m) { size_t selCnt=0; - //for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) - // if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; for (auto v: m.vert) if(!v.IsD() && v.IsS()) ++selCnt; return selCnt; @@ -305,7 +299,7 @@ static size_t VertexCount(const MeshType &m) static size_t TetraCount (const MeshType & m) { size_t selCnt = 0; - ForEachTetra(m, [&selCnt] (TetraType & t) { + ForEachTetra(m, [&selCnt] (const TetraType & t) { if (t.IsS()) ++selCnt; }); From 6f4e196236f3b5c36de921e16a3d4c1bf79e7f1e Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 11 Sep 2020 15:09:02 +0200 Subject: [PATCH 009/140] templating callable function in foreachs to allow usage of lambdas --- vcg/complex/foreach.h | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/vcg/complex/foreach.h b/vcg/complex/foreach.h index 4f7710fd..a062e41c 100644 --- a/vcg/complex/foreach.h +++ b/vcg/complex/foreach.h @@ -34,8 +34,8 @@ namespace tri { @{ */ -template -inline void ForEachFacePos(const MeshType &m, std::function &)> action) +template +inline void ForEachFacePos(const MeshType &m, Callable action) { typedef typename face::Pos PosType; @@ -50,8 +50,8 @@ inline void ForEachFacePos(const MeshType &m, std::function -inline void ForEachFacePos(MeshType &m, std::function &)> action) +template +inline void ForEachFacePos(MeshType &m, Callable action) { typedef typename face::Pos PosType; @@ -76,8 +76,8 @@ inline void ForEachFacePos(MeshType &m, std::function -inline void ForEachFace(const MeshType &m, std::function action) +template +inline void ForEachFace(const MeshType &m, Callable action) { if(m.fn == (int) m.face.size()) { @@ -95,8 +95,8 @@ inline void ForEachFace(const MeshType &m, std::function -inline void ForEachFace(MeshType &m, std::function action) +template +inline void ForEachFace(MeshType &m, Callable action) { if(m.fn == (int) m.face.size()) { @@ -124,8 +124,8 @@ inline void ForEachFace(MeshType &m, std::function -inline void ForEachVertex(const MeshType &m, std::function action) +template +inline void ForEachVertex(const MeshType &m, Callable action) { if(m.vn == (int) m.vert.size()) { @@ -143,8 +143,8 @@ inline void ForEachVertex(const MeshType &m, std::function -inline void ForEachVertex(MeshType &m, std::function action) +template +inline void ForEachVertex(MeshType &m, Callable action) { if(m.vn == (int) m.vert.size()) { @@ -172,8 +172,8 @@ inline void ForEachVertex(MeshType &m, std::function -inline void ForEachHEdge(const MeshType &m, std::function action) +template +inline void ForEachHEdge(const MeshType &m, Callable action) { if(m.hn == (int) m.hedge.size()) { @@ -191,8 +191,8 @@ inline void ForEachHEdge(const MeshType &m, std::function -inline void ForEachHEdge(MeshType &m, std::function action) +template +inline void ForEachHEdge(MeshType &m, Callable action) { if(m.hn == (int) m.hedge.size()) { @@ -220,8 +220,8 @@ inline void ForEachHEdge(MeshType &m, std::function -inline void ForEachEdge(const MeshType &m, std::function action) +template +inline void ForEachEdge(const MeshType &m, Callable action) { if(m.en == (int) m.edge.size()) { @@ -239,8 +239,8 @@ inline void ForEachEdge(const MeshType &m, std::function -inline void ForEachEdge(MeshType &m, std::function action) +template +inline void ForEachEdge(MeshType &m, Callable action) { if(m.en == (int) m.edge.size()) { @@ -268,8 +268,8 @@ inline void ForEachEdge(MeshType &m, std::function -inline void ForEachTetra(const MeshType &m, std::function action) +template +inline void ForEachTetra(const MeshType &m, Callable action) { if(m.tn == (int) m.tetra.size()) { @@ -287,8 +287,8 @@ inline void ForEachTetra(const MeshType &m, std::function -inline void ForEachTetra(MeshType &m, std::function action) +template +inline void ForEachTetra(MeshType &m, Callable action) { if(m.tn == (int) m.tetra.size()) { From 55b55abdeddf947136b4e3682829953e95032b7f Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 11 Sep 2020 15:30:57 +0200 Subject: [PATCH 010/140] foreach used in selection.h --- vcg/complex/algorithms/update/selection.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index 30cc5a8f..221db704 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -183,6 +183,7 @@ typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::EdgeIterator EdgeIterator; +typedef typename MeshType::EdgeType EdgeType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; @@ -272,8 +273,9 @@ static void Clear(MeshType &m) static size_t FaceCount(const MeshType &m) { size_t selCnt=0; - for (auto f: m.face) - if(!f.IsD() && f.IsS()) ++selCnt; + ForEachFace(m, [&](const FaceType& f){ + if(f.IsS()) ++selCnt; + }); return selCnt; } @@ -281,8 +283,9 @@ static size_t FaceCount(const MeshType &m) static size_t EdgeCount(const MeshType &m) { size_t selCnt=0; - for (auto e: m.edge) - if(!e.IsD() && e.IsS()) ++selCnt; + ForEachEdge(m, [&](const EdgeType& e){ + if(e.IsS()) ++selCnt; + }); return selCnt; } @@ -290,8 +293,9 @@ static size_t EdgeCount(const MeshType &m) static size_t VertexCount(const MeshType &m) { size_t selCnt=0; - for (auto v: m.vert) - if(!v.IsD() && v.IsS()) ++selCnt; + ForEachVertex(m, [&](const VertexType& v){ + if(v.IsS()) ++selCnt; + }); return selCnt; } @@ -299,9 +303,8 @@ static size_t VertexCount(const MeshType &m) static size_t TetraCount (const MeshType & m) { size_t selCnt = 0; - ForEachTetra(m, [&selCnt] (const TetraType & t) { - if (t.IsS()) - ++selCnt; + ForEachTetra(m, [&] (const TetraType & t) { + if (t.IsS()) ++selCnt; }); return selCnt; From fb40a0f78aff0d34f00def4db25d35cda2b3f548 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 16 Oct 2020 13:23:41 +0200 Subject: [PATCH 011/140] fixed const correctness and added point-segment distance on Segment2 --- vcg/space/segment2.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vcg/space/segment2.h b/vcg/space/segment2.h index 05e92056..4f1407ce 100644 --- a/vcg/space/segment2.h +++ b/vcg/space/segment2.h @@ -142,7 +142,7 @@ typedef Segment2 Segment2f; typedef Segment2 Segment2d; template -Point2 ClosestPoint( Segment2 s, const Point2 & p) +Point2 ClosestPoint(const Segment2 & s, const Point2 & p) { vcg::Line2 l; l.Set(s.P0(),s.P1()-s.P0()); @@ -157,6 +157,12 @@ Point2 ClosestPoint( Segment2 s, const Point2 +ScalarType Distance(const Segment2 & s, const Point2 & p) { + const Point2 c = ClosestPoint(s, p); + return (c - p).Norm(); +} + template class PointSegment2DEPFunctor { public: From 659d2d12f23b0ccfb1c04ed9dcc112b6509c3a35 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 16 Oct 2020 14:15:40 +0200 Subject: [PATCH 012/140] removed deprecated std::unary_function --- vcg/complex/algorithms/cylinder_clipping.h | 2 +- vcg/complex/algorithms/quadrangulator.h | 2 +- vcg/complex/algorithms/refine.h | 16 ++++++++-------- vcg/complex/algorithms/refine_loop.h | 4 ++-- vcg/space/deprecated_point.h | 1 + 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/vcg/complex/algorithms/cylinder_clipping.h b/vcg/complex/algorithms/cylinder_clipping.h index 7e2849fc..14c7e9ad 100644 --- a/vcg/complex/algorithms/cylinder_clipping.h +++ b/vcg/complex/algorithms/cylinder_clipping.h @@ -276,7 +276,7 @@ public: } }; - class CylMidPoint : public std::unary_function + class CylMidPoint { private: CylMidPoint() {assert(0);} diff --git a/vcg/complex/algorithms/quadrangulator.h b/vcg/complex/algorithms/quadrangulator.h index 3cc08097..70e44769 100644 --- a/vcg/complex/algorithms/quadrangulator.h +++ b/vcg/complex/algorithms/quadrangulator.h @@ -318,7 +318,7 @@ private: // In this implemenation we simply put the new vertex in the MidPoint position. // Color and TexCoords are interpolated accordingly. template - struct SplitMidPoint : public std::unary_function , typename MESH_TYPE::CoordType > + struct SplitMidPoint { typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::FaceType FaceType; diff --git a/vcg/complex/algorithms/refine.h b/vcg/complex/algorithms/refine.h index 65212987..cd3c75a6 100644 --- a/vcg/complex/algorithms/refine.h +++ b/vcg/complex/algorithms/refine.h @@ -122,7 +122,7 @@ struct BaseInterpolator // providing, in the constructor, an interpolator functor that will be called for each new vertex to be created. template > -struct MidPoint : public std::unary_function , typename MESH_TYPE::CoordType > +struct MidPoint { typedef typename face::Pos PosType; typedef typename MESH_TYPE::VertexType VertexType; @@ -179,7 +179,7 @@ struct MidPoint : public std::unary_function -struct MidPointArc : public std::unary_function , typename MESH_TYPE::CoordType> +struct MidPointArc { void operator()(typename MESH_TYPE::VertexType &nv, face::Pos ep) { @@ -251,7 +251,7 @@ A non linear subdivision scheme for triangle meshes */ template -struct MidPointArcNaive : public std::unary_function< face::Pos , typename MESH_TYPE::CoordType> +struct MidPointArcNaive { typename MESH_TYPE::CoordType operator()(face::Pos ep) { @@ -575,7 +575,7 @@ Siggraph 2000 Course Notes */ template -struct MidPointButterfly : public std::unary_function , typename MESH_TYPE::CoordType> +struct MidPointButterfly { MESH_TYPE &m; MidPointButterfly(MESH_TYPE &_m):m(_m){} @@ -689,7 +689,7 @@ struct MidPointButterfly : public std::unary_function -struct MidPointButterfly2 : public std::unary_function , typename MESH_TYPE::CoordType> +struct MidPointButterfly2 { typename MESH_TYPE::CoordType operator()(face::Pos ep) { @@ -780,7 +780,7 @@ face::Pos he(ep.f,ep.z,ep.f->V(ep.z)); */ template -class QualityMidPointFunctor : public std::unary_function , typename MESH_TYPE::CoordType> +class QualityMidPointFunctor { public: typedef Point3 Point3x; @@ -843,7 +843,7 @@ class QualityEdgePredicate template -struct MidPointSphere : public std::unary_function , typename MESH_TYPE::CoordType> +struct MidPointSphere { Sphere3 sph; typedef Point3 Point3x; @@ -889,7 +889,7 @@ class EdgeSplSphere }; template -struct CenterPointBarycenter : public std::unary_function +struct CenterPointBarycenter { typename TRIMESH_TYPE::CoordType operator()(typename TRIMESH_TYPE::FacePointer f){ return vcg::Barycenter(*f); diff --git a/vcg/complex/algorithms/refine_loop.h b/vcg/complex/algorithms/refine_loop.h index eab257b4..bd631bfb 100644 --- a/vcg/complex/algorithms/refine_loop.h +++ b/vcg/complex/algorithms/refine_loop.h @@ -340,7 +340,7 @@ struct LS3Projection { }; template, class WEIGHT_TYPE=LoopWeight > -struct OddPointLoopGeneric : public std::unary_function , typename MESH_TYPE::VertexType> +struct OddPointLoopGeneric { typedef METHOD_TYPE Projection; typedef WEIGHT_TYPE Weight; @@ -427,7 +427,7 @@ struct OddPointLoopGeneric : public std::unary_function, class WEIGHT_TYPE=LoopWeight > -struct EvenPointLoopGeneric : public std::unary_function , typename MESH_TYPE::VertexType> +struct EvenPointLoopGeneric { typedef METHOD_TYPE Projection; typedef WEIGHT_TYPE Weight; diff --git a/vcg/space/deprecated_point.h b/vcg/space/deprecated_point.h index f5cf4585..c973fa81 100644 --- a/vcg/space/deprecated_point.h +++ b/vcg/space/deprecated_point.h @@ -733,6 +733,7 @@ public: return Point4( _v[0]*s, _v[1]*s , _v[2]*s , _v[3]*s ); } inline PointType operator ^ ( PointType const & p ) const { + (void)p; assert(0); return *this; } From d7cbcfa1dcb6dbceb195fe085a78b12b76d8a149 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 16 Oct 2020 14:43:39 +0200 Subject: [PATCH 013/140] removed all deprecated std::unary_function --- vcg/space/index/spatial_hashing.h | 4 +--- vcg/space/index/spatial_hashing2d.h | 7 +------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/vcg/space/index/spatial_hashing.h b/vcg/space/index/spatial_hashing.h index 449017c0..df17e169 100644 --- a/vcg/space/index/spatial_hashing.h +++ b/vcg/space/index/spatial_hashing.h @@ -33,10 +33,8 @@ namespace vcg{ - - // hashing function - struct HashFunctor : public std::unary_function + struct HashFunctor { enum { // parameters for hash table diff --git a/vcg/space/index/spatial_hashing2d.h b/vcg/space/index/spatial_hashing2d.h index ae27a3b2..a8d0c407 100644 --- a/vcg/space/index/spatial_hashing2d.h +++ b/vcg/space/index/spatial_hashing2d.h @@ -52,10 +52,8 @@ namespace vcg{ - - // hashing function - struct HashFunctor2D : public std::unary_function + struct HashFunctor2D { enum { // parameters for hash table @@ -78,9 +76,6 @@ namespace vcg{ } }; - - - /** Spatial Hash Table Spatial Hashing as described in "Optimized Spatial Hashing for Coll ision Detection of Deformable Objects", From e807f54280f5735888bb871bbd7536fb90f2312f Mon Sep 17 00:00:00 2001 From: nico Date: Mon, 26 Oct 2020 16:28:10 +0100 Subject: [PATCH 014/140] added IsD per face check on Computing Normal Function --- vcg/complex/algorithms/polygonal_algorithms.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index bda99570..99805895 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -416,6 +416,7 @@ public: static void UpdateFaceNormals(PolyMeshType &poly_m) { for (size_t i=0;i Date: Thu, 29 Oct 2020 14:35:04 +0100 Subject: [PATCH 015/140] added IsD() check for each vertex --- vcg/complex/algorithms/polygonal_algorithms.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index 99805895..1fa638bb 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -740,8 +740,7 @@ public: for (size_t i=0;i Date: Thu, 29 Oct 2020 14:51:31 +0100 Subject: [PATCH 016/140] added IsD check in LaplacianPos Function --- vcg/complex/algorithms/polygonal_algorithms.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index 1fa638bb..0c517f90 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -334,7 +334,10 @@ private: AvVert.clear(); AvVert.resize(poly_m.vert.size(),CoordType(0,0,0)); std::vector AvSum(poly_m.vert.size(),0); - for (size_t i=0;i Date: Sat, 31 Oct 2020 22:10:05 +0100 Subject: [PATCH 017/140] added displacement of polygonal template position considering the fixed vertices --- vcg/complex/algorithms/polygonal_algorithms.h | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index 0c517f90..a57625b9 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -387,6 +387,30 @@ private: F.N()=PlF.Direction(); } + static void DisplaceBySelected(FaceType &f,std::vector &TemplatePos, + bool FixS,bool FixB) + { + CoordType AvPosF(0,0,0); + CoordType AvPosT(0,0,0); + size_t Num=0; + for (size_t i=0;iIsS())); + AddVal|=((FixB)&&(f.V(i)->IsB())); + if (!AddVal)continue; + Num++; + AvPosF+=f.V(i)->P(); + AvPosT+=TemplatePos[i]; + } + if (Num==0)return; + AvPosF/=(ScalarType)Num; + AvPosT/=(ScalarType)Num; + CoordType Displ=AvPosF-AvPosT; + for (size_t i=0;i TemplatePos; GetRotatedTemplatePos(poly_m.face[i],TemplatePos); + if ((FixS)||(fixB)) + DisplaceBySelected(poly_m.face[i],TemplatePos,FixS,fixB); + //then cumulate the position per vertex ScalarType val=vcg::PolyArea(poly_m.face[i]); if (val<(AvgArea*0.00001)) @@ -564,7 +591,6 @@ public: //sum up contributes avgPos[IndexV]+=Pos*W; weightSum[IndexV]+=W; - } } From 84095352550f68af89ccdae2b3557d981e7edfff Mon Sep 17 00:00:00 2001 From: korialis Date: Thu, 12 Nov 2020 16:38:56 +0100 Subject: [PATCH 018/140] minor changes in isotropic remesher --- vcg/complex/algorithms/isotropic_remeshing.h | 2522 +++++++++--------- 1 file changed, 1272 insertions(+), 1250 deletions(-) diff --git a/vcg/complex/algorithms/isotropic_remeshing.h b/vcg/complex/algorithms/isotropic_remeshing.h index ae18c5fe..06ea33bb 100644 --- a/vcg/complex/algorithms/isotropic_remeshing.h +++ b/vcg/complex/algorithms/isotropic_remeshing.h @@ -41,1318 +41,1340 @@ template class IsotropicRemeshing { public: - typedef TRI_MESH_TYPE MeshType; - typedef typename MeshType::FaceType FaceType; - typedef typename MeshType::FacePointer FacePointer; - typedef typename FaceType::VertexType VertexType; - typedef typename FaceType::VertexPointer VertexPointer; - typedef typename VertexType::ScalarType ScalarType; - typedef typename VertexType::CoordType CoordType; - typedef typename face::Pos PosType; - typedef BasicVertexPair VertexPair; - typedef EdgeCollapser Collapser; - typedef GridStaticPtr StaticGrid; + typedef TRI_MESH_TYPE MeshType; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FacePointer FacePointer; + typedef typename FaceType::VertexType VertexType; + typedef typename FaceType::VertexPointer VertexPointer; + typedef typename VertexType::ScalarType ScalarType; + typedef typename VertexType::CoordType CoordType; + typedef typename face::Pos PosType; + typedef BasicVertexPair VertexPair; + typedef EdgeCollapser Collapser; + typedef GridStaticPtr StaticGrid; - typedef struct Params { - typedef struct Stat { - int splitNum; - int collapseNum; - int flipNum; + typedef struct Params { + typedef struct Stat { + int splitNum; + int collapseNum; + int flipNum; - void Reset() { - splitNum=0; - collapseNum=0; - flipNum=0; - } - } Stat; + void Reset() { + splitNum=0; + collapseNum=0; + flipNum=0; + } + } Stat; - ScalarType minLength; // minimal admitted length: no edge should be shorter than this value (used when collapsing) - ScalarType maxLength; // maximal admitted length: no edge should be longer than this value (used when refining) - ScalarType lengthThr; + ScalarType minLength; // minimal admitted length: no edge should be shorter than this value (used when collapsing) + ScalarType maxLength; // maximal admitted length: no edge should be longer than this value (used when refining) + ScalarType lengthThr; - ScalarType minimalAdmittedArea; - ScalarType maxSurfDist; + ScalarType minimalAdmittedArea; + ScalarType maxSurfDist; - ScalarType aspectRatioThr = 0.05; //min aspect ratio: during relax bad triangles will be relaxed - ScalarType foldAngleCosThr = cos(math::ToRad(140.)); //min angle to be considered folding: during relax folded triangles will be relaxed + ScalarType aspectRatioThr = 0.05; //min aspect ratio: during relax bad triangles will be relaxed + ScalarType foldAngleCosThr = cos(math::ToRad(140.)); //min angle to be considered folding: during relax folded triangles will be relaxed - ScalarType creaseAngleRadThr = math::ToRad(10.0); - ScalarType creaseAngleCosThr = cos(math::ToRad(10.0)); //min angle to be considered crease: two faces with normals diverging more than thr share a crease edge + ScalarType creaseAngleRadThr = math::ToRad(10.0); + ScalarType creaseAngleCosThr = cos(math::ToRad(10.0)); //min angle to be considered crease: two faces with normals diverging more than thr share a crease edge - bool splitFlag = true; - bool swapFlag = true; - bool collapseFlag = true; - bool smoothFlag=true; - bool projectFlag=true; - bool selectedOnly = false; - bool cleanFlag = true; + bool splitFlag = true; + bool swapFlag = true; + bool collapseFlag = true; + bool smoothFlag=true; + bool projectFlag=true; + bool selectedOnly = false; + bool cleanFlag = true; - bool userSelectedCreases = false; - bool surfDistCheck = true; + bool userSelectedCreases = false; + bool surfDistCheck = true; - bool adapt=false; - int iter=1; - Stat stat; + bool adapt=false; + int iter=1; + Stat stat; - void SetTargetLen(const ScalarType len) - { - minLength=len*4./5.; - maxLength=len*4./3.; - lengthThr=len*4./3.; - minimalAdmittedArea = (minLength * minLength)/1000.0; - } - - void SetFeatureAngleDeg(const ScalarType angle) - { - creaseAngleRadThr = math::ToRad(angle); - creaseAngleCosThr = cos(creaseAngleRadThr); - } + void SetTargetLen(const ScalarType len) + { + minLength=len*4./5.; + maxLength=len*4./3.; + lengthThr=len*4./3.; + minimalAdmittedArea = (minLength * minLength)/1000.0; + } - StaticGrid grid; - MeshType* m; - MeshType* mProject; + void SetFeatureAngleDeg(const ScalarType angle) + { + creaseAngleRadThr = math::ToRad(angle); + creaseAngleCosThr = cos(creaseAngleRadThr); + } - } Params; + StaticGrid grid; + MeshType* m; + MeshType* mProject; + + } Params; private: - static void debug_crease (MeshType & toRemesh, std::string prepend, int i) - { - ForEachVertex(toRemesh, [] (VertexType & v) { - v.C() = Color4b::Gray; - v.Q() = 0; - }); + static void debug_crease (MeshType & toRemesh, std::string prepend, int i) + { + ForEachVertex(toRemesh, [] (VertexType & v) { + v.C() = Color4b::Gray; + v.Q() = 0; + }); - ForEachFacePos(toRemesh, [&](PosType &p){ - if (p.F()->IsFaceEdgeS(p.E())) - { - p.V()->Q() += 1; - p.VFlip()->Q() += 1; - } - }); + ForEachFacePos(toRemesh, [&](PosType &p){ + if (p.F()->IsFaceEdgeS(p.E())) + { + p.V()->Q() += 1; + p.VFlip()->Q() += 1; + } + }); - ForEachVertex(toRemesh, [] (VertexType & v) { - if (v.Q() >= 4) - v.C() = Color4b::Green; - else if (v.Q() >= 2) - v.C() = Color4b::Red; - }); - prepend += "_creases" + std::to_string(i) + ".ply"; - vcg::tri::io::Exporter::Save(toRemesh, prepend.c_str(), vcg::tri::io::Mask::IOM_ALL); - } + ForEachVertex(toRemesh, [] (VertexType & v) { + if (v.Q() >= 4) + v.C() = Color4b::Green; + else if (v.Q() >= 2) + v.C() = Color4b::Red; + }); + prepend += "_creases" + std::to_string(i) + ".ply"; + vcg::tri::io::Exporter::Save(toRemesh, prepend.c_str(), vcg::tri::io::Mask::IOM_ALL); + } - static void removeColinearFaces(MeshType & m, Params & params) - { - vcg::tri::UpdateTopology::FaceFace(m); + static void removeColinearFaces(MeshType & m, Params & params) + { + vcg::tri::UpdateTopology::FaceFace(m); - int count = 0; + int count = 0; int iter = 0; - do - { - vcg::tri::UpdateTopology::FaceFace(m); - vcg::tri::UnMarkAll(m); + do + { + vcg::tri::UpdateTopology::FaceFace(m); + vcg::tri::UnMarkAll(m); - count = 0; - for (size_t i = 0; i < size_t(m.FN()); ++i) - { - FaceType & f = m.face[i]; + count = 0; + for (size_t i = 0; i < size_t(m.FN()); ++i) + { + FaceType & f = m.face[i]; - ScalarType quality = vcg::QualityRadii(f.cP(0), f.cP(1), f.cP(2)); + ScalarType quality = vcg::QualityRadii(f.cP(0), f.cP(1), f.cP(2)); if (quality <= 0.001) - { - //find longest edge - double edges[3]; - edges[0] = vcg::Distance(f.cP(0), f.cP(1)); - edges[1] = vcg::Distance(f.cP(1), f.cP(2)); - edges[2] = vcg::Distance(f.cP(2), f.cP(0)); + { + //find longest edge + double edges[3]; + edges[0] = vcg::Distance(f.cP(0), f.cP(1)); + edges[1] = vcg::Distance(f.cP(1), f.cP(2)); + edges[2] = vcg::Distance(f.cP(2), f.cP(0)); ScalarType smallestEdge = std::min(edges[0], std::min(edges[1], edges[2])); int longestIdx = std::find(edges, edges+3, std::max(std::max(edges[0], edges[1]), edges[2])) - (edges); - if (vcg::tri::IsMarked(m, f.V2(longestIdx))) - continue; + if (vcg::tri::IsMarked(m, f.V2(longestIdx))) + continue; - auto f1 = f.cFFp(longestIdx); - vcg::tri::Mark(m,f.V2(longestIdx)); - if (!vcg::face::IsBorder(f, longestIdx) && vcg::face::IsManifold(f, longestIdx) && vcg::face::checkFlipEdgeNotManifold(f, longestIdx)) { + auto f1 = f.cFFp(longestIdx); + vcg::tri::Mark(m,f.V2(longestIdx)); + if (!vcg::face::IsBorder(f, longestIdx) && vcg::face::IsManifold(f, longestIdx) && vcg::face::checkFlipEdgeNotManifold(f, longestIdx)) { - // Check if EdgeFlipping improves quality - FacePointer g = f.FFp(longestIdx); int k = f.FFi(longestIdx); - vcg::Triangle3 t1(f.P(longestIdx), f.P1(longestIdx), f.P2(longestIdx)), t2(g->P(k), g->P1(k), g->P2(k)), - t3(f.P(longestIdx), g->P2(k), f.P2(longestIdx)), t4(g->P(k), f.P2(longestIdx), g->P2(k)); + // Check if EdgeFlipping improves quality + FacePointer g = f.FFp(longestIdx); int k = f.FFi(longestIdx); + vcg::Triangle3 t1(f.P(longestIdx), f.P1(longestIdx), f.P2(longestIdx)), t2(g->P(k), g->P1(k), g->P2(k)), + t3(f.P(longestIdx), g->P2(k), f.P2(longestIdx)), t4(g->P(k), f.P2(longestIdx), g->P2(k)); - if ( std::min( QualityFace(t1), QualityFace(t2) ) <= std::min( QualityFace(t3), QualityFace(t4) )) - { - ScalarType dist; - CoordType closest; + auto n1 = vcg::TriangleNormal(t1); + auto n2 = vcg::TriangleNormal(t2); + auto n3 = vcg::TriangleNormal(t3); + auto n4 = vcg::TriangleNormal(t4); + + auto biggestSmallest = vcg::DoubleArea(t1) > vcg::DoubleArea(t2) ? std::make_pair(t1, t2) : std::make_pair(t2, t1); + auto areaRatio = vcg::DoubleArea(biggestSmallest.first) / vcg::DoubleArea(biggestSmallest.second); + + bool normalCheck = true; +// if (n1.Norm() > 0.001 && n2.Norm() > 0.001) + { + auto referenceNormal = vcg::NormalizedTriangleNormal(biggestSmallest.first); + + normalCheck &= vcg::NormalizedTriangleNormal(t3) * referenceNormal >= 0.95; + normalCheck &= vcg::NormalizedTriangleNormal(t4) * referenceNormal >= 0.95; + } + + bool areaCheck = false; + if (areaRatio > 1000) + { + areaCheck |= vcg::DoubleArea(t3) / vcg::DoubleArea(biggestSmallest.second) > 1000 && vcg::DoubleArea(t4) / vcg::DoubleArea(biggestSmallest.second) > 1000; + } + + if ((normalCheck) && (areaCheck || std::min( QualityFace(t1), QualityFace(t2) ) <= std::min( QualityFace(t3), QualityFace(t4)))) + { + ScalarType dist; + CoordType closest; auto fp0 = vcg::tri::GetClosestFaceBase(*params.mProject, params.grid, vcg::Barycenter(t3), smallestEdge/4., dist, closest); - if (fp0 == NULL) - continue; + if (fp0 == NULL) + continue; auto fp1 = vcg::tri::GetClosestFaceBase(*params.mProject, params.grid, vcg::Barycenter(t4), smallestEdge/4., dist, closest); - if (fp1 == NULL) - continue; + if (fp1 == NULL) + continue; - vcg::face::FlipEdgeNotManifold(f, longestIdx); - ++count; - } - } - } - } - } while (count && ++iter < 50); - } + vcg::face::FlipEdgeNotManifold(f, longestIdx); + ++count; + } + } + } + } + } while (count && ++iter < 75); - static void cleanMesh(MeshType & m, Params & params) - { - vcg::tri::Clean::RemoveDuplicateFace(m); - vcg::tri::Clean::RemoveUnreferencedVertex(m); - vcg::tri::Allocator::CompactEveryVector(m); + } - vcg::tri::UpdateTopology::FaceFace(m); - removeColinearFaces(m, params); - vcg::tri::UpdateTopology::FaceFace(m); - } + static void cleanMesh(MeshType & m, Params & params) + { + vcg::tri::Clean::RemoveDuplicateFace(m); + vcg::tri::Clean::RemoveUnreferencedVertex(m); + vcg::tri::Allocator::CompactEveryVector(m); + + vcg::tri::UpdateTopology::FaceFace(m); + removeColinearFaces(m, params); + vcg::tri::UpdateTopology::FaceFace(m); + } public: - static void Do(MeshType &toRemesh, Params & params, vcg::CallBackPos * cb=0) - { - MeshType toProjectCopy; - tri::UpdateBounding::Box(toRemesh); - tri::UpdateNormal::PerVertexNormalizedPerFaceNormalized(toRemesh); + static void Do(MeshType &toRemesh, Params & params, vcg::CallBackPos * cb=0) + { + MeshType toProjectCopy; + tri::UpdateBounding::Box(toRemesh); + tri::UpdateNormal::PerVertexNormalizedPerFaceNormalized(toRemesh); - tri::Append::MeshCopy(toProjectCopy, toRemesh); + tri::Append::MeshCopy(toProjectCopy, toRemesh); - Do(toRemesh,toProjectCopy,params,cb); - } - static void Do(MeshType &toRemesh, MeshType &toProject, Params & params, vcg::CallBackPos * cb=0) - { - assert(&toRemesh != &toProject); - params.stat.Reset(); + Do(toRemesh,toProjectCopy,params,cb); + } + static void Do(MeshType &toRemesh, MeshType &toProject, Params & params, vcg::CallBackPos * cb=0) + { + assert(&toRemesh != &toProject); + params.stat.Reset(); - tri::UpdateBounding::Box(toRemesh); + tri::UpdateBounding::Box(toRemesh); - { - tri::UpdateBounding::Box(toProject); - tri::UpdateNormal::PerFaceNormalized(toProject); - params.m = &toRemesh; - params.mProject = &toProject; - params.grid.Set(toProject.face.begin(), toProject.face.end()); - } + { + tri::UpdateBounding::Box(toProject); + tri::UpdateNormal::PerFaceNormalized(toProject); + params.m = &toRemesh; + params.mProject = &toProject; + params.grid.Set(toProject.face.begin(), toProject.face.end()); + } - if (params.cleanFlag) - cleanMesh(toRemesh, params); + if (params.cleanFlag) + cleanMesh(toRemesh, params); - tri::UpdateTopology::FaceFace(toRemesh); - tri::UpdateFlags::VertexBorderFromFaceAdj(toRemesh); - tri::UpdateTopology::VertexFace(toRemesh); + tri::UpdateTopology::FaceFace(toRemesh); + tri::UpdateFlags::VertexBorderFromFaceAdj(toRemesh); + tri::UpdateTopology::VertexFace(toRemesh); - // computeQuality(toRemesh); - // tri::UpdateQuality::VertexSaturate(toRemesh); + // computeQuality(toRemesh); + // tri::UpdateQuality::VertexSaturate(toRemesh); - tagCreaseEdges(toRemesh, params); + tagCreaseEdges(toRemesh, params); - for(int i=0; i < params.iter; ++i) - { - // params.stat.Reset(); - if(cb) cb(100*i/params.iter, "Remeshing"); + for(int i=0; i < params.iter; ++i) + { + // params.stat.Reset(); + if(cb) cb(100*i/params.iter, "Remeshing"); - if(params.splitFlag) - SplitLongEdges(toRemesh, params); + if(params.splitFlag) + SplitLongEdges(toRemesh, params); #ifdef DEBUG_CREASE - debug_crease(toRemesh, std::string("after_ref"), i); + debug_crease(toRemesh, std::string("after_ref"), i); #endif - if(params.collapseFlag) - { - CollapseShortEdges(toRemesh, params); - CollapseCrosses(toRemesh, params); - } + if(params.collapseFlag) + { + CollapseShortEdges(toRemesh, params); + CollapseCrosses(toRemesh, params); + } - if(params.swapFlag) - ImproveValence(toRemesh, params); + if(params.swapFlag) + ImproveValence(toRemesh, params); - if(params.smoothFlag) - ImproveByLaplacian(toRemesh, params); + if(params.smoothFlag) + ImproveByLaplacian(toRemesh, params); - if(params.projectFlag) - ProjectToSurface(toRemesh, params); - } - } + if(params.projectFlag) + ProjectToSurface(toRemesh, params); + } + } private: - /* - TODO: Add better crease support: detect all creases at starting time, saving it on facedgesel flags - All operations must then preserve the faceedgesel flag accordingly: - Refinement -> Check that refiner propagates faceedgesel [should be doing it] - Collapse -> Implement 1D edge collapse and better check on corners and creases - Swap -> Totally avoid swapping crease edges [ok] - Smooth -> Apply 1D smoothing to crease vertices + check on - (http://www.cs.ubc.ca/labs/imager/tr/2009/eltopo/sisc2009.pdf) - */ - IsotropicRemeshing() {} - // this returns the value of cos(a) where a is the angle between n0 and n1. (scalar prod is cos(a)) - static inline ScalarType fastAngle(Point3 n0, Point3 n1) - { - return math::Clamp(n0*n1,(ScalarType)-1.0,(ScalarType)1.0); - } - // compare the value of the scalar prod with the cos of the crease threshold - static inline bool testCreaseEdge(PosType &p, ScalarType creaseCosineThr) - { - ScalarType angle = fastAngle(NormalizedTriangleNormal(*(p.F())), NormalizedTriangleNormal(*(p.FFlip()))); - return angle <= creaseCosineThr && angle >= -0.98; - // return (angle <= creaseCosineThr && angle >= -creaseCosineThr); - } - // this stores in minQ the value of the 10th percentile of the VertQuality distribution and in - // maxQ the value of the 90th percentile. - static inline void computeVQualityDistrMinMax(MeshType &m, ScalarType &minQ, ScalarType &maxQ) - { - Distribution distr; - tri::Stat::ComputePerVertexQualityDistribution(m,distr); - - maxQ = distr.Percentile(0.9f); - minQ = distr.Percentile(0.1f); - } - - //Computes PerVertexQuality as a function of the 'deviation' of the normals taken from - //the faces incident to each vertex - static void computeQuality(MeshType &m) - { - tri::RequirePerVertexQuality(m); - tri::UpdateFlags::VertexClearV(m); - - for(auto vi=m.vert.begin(); vi!=m.vert.end(); ++vi) - if(!(*vi).IsD()) - { - vector ff; - face::VFExtendedStarVF(&*vi, 0, ff); - - ScalarType tot = 0.f; - auto it = ff.begin(); - Point3 fNormal = NormalizedTriangleNormal(**it); - ++it; - while(it != ff.end()) - { - tot+= 1-math::Abs(fastAngle(fNormal, NormalizedTriangleNormal(**it))); - ++it; - } - vi->Q() = tot / (ScalarType)(std::max(1, ((int)ff.size()-1))); - vi->SetV(); - } - } - - /* - Computes the ideal valence for the vertex in pos p: - 4 for border vertices - 6 for internal vertices - */ - static inline int idealValence(PosType &p) - { - if(p.IsBorder()) return 4; - return 6; - } - static inline int idealValence(VertexType &v) - { - if(v.IsB()) return 4; - return 6; - } - static inline int idealValenceSlow(PosType &p) - { - std::vector posVec; - VFOrderedStarFF(p,posVec); - float angleSumRad =0; - for(PosType &ip : posVec) - { - angleSumRad += ip.AngleRad(); - } - - return (int)(std::ceil(angleSumRad / (M_PI/3.0f))); - } - - static bool testHausdorff (MeshType & m, StaticGrid & grid, const std::vector & verts, const ScalarType maxD) - { - for (CoordType v : verts) - { - CoordType closest; - ScalarType dist = 0; - FaceType* fp = GetClosestFaceBase(m, grid, v, maxD, dist, closest); - - if (fp == NULL) - { - return false; - } - } - return true; - } - - static int tagCreaseEdges(MeshType &m, Params & params) - { - int count = 0; - std::vector creaseVerts(m.VN(), 0); - - vcg::tri::UpdateFlags::VertexClearV(m); - std::queue creaseQueue; - ForEachFacePos(m, [&](PosType &p){ - - if (p.IsBorder()) - p.F()->SetFaceEdgeS(p.E()); - - // if((p.FFlip() > p.F())) - { - FaceType *ff = p.F(); - FaceType *ffAdj = p.FFlip(); - - double quality = vcg::QualityRadii(ff->cP(0), ff->cP(1), ff->cP(2)); - double qualityAdj = vcg::QualityRadii(ffAdj->cP(0), ffAdj->cP(1), ffAdj->cP(2)); - - bool qualityCheck = quality > 0.00000001 && qualityAdj > 0.00000001; -// bool areaCheck = vcg::DoubleArea(*ff) > 0.000001 && vcg::DoubleArea(*ffAdj) > 0.000001; - - if (!params.userSelectedCreases && (testCreaseEdge(p, params.creaseAngleCosThr) /*&& areaCheck*//* && qualityCheck*/) || p.IsBorder()) - { - PosType pp = p; - do { - pp.F()->SetFaceEdgeS(pp.E()); - pp.NextF(); - } while (pp != p); - - creaseQueue.push(p); - } - } - }); - - // //now all creases are checked... - // //prune false positive (too small) (count + scale?) - - // while (!creaseQueue.empty()) - // { - // PosType & p = creaseQueue.front(); - // creaseQueue.pop(); - - // std::stack chainQueue; - // std::vector chainVerts; - - // if (!p.V()->IsV()) - // { - // chainQueue.push(p); - // } - - // p.FlipV(); - // p.NextEdgeS(); - - // if (!p.V()->IsV()) - // { - // chainQueue.push(p); - // } - - // while (!chainQueue.empty()) - // { - // PosType p = chainQueue.top(); - // chainQueue.pop(); - - // p.V()->SetV(); - // chainVerts.push_back(vcg::tri::Index(m, p.V())); - - // PosType pp = p; - - // //circle around vert in search for new crease edges - // do { - // pp.NextF(); //jump adj face - // pp.FlipE(); // this edge is already ok => jump to next - // if (pp.IsEdgeS()) - // { - // PosType nextPos = pp; - // nextPos.FlipV(); // go to next vert in the chain - // if (!nextPos.V()->IsV()) // if already visited...ignore - // { - // chainQueue.push(nextPos); - // } - // } - // } - // while (pp != p); - - // } - - // if (chainVerts.size() > 5) - // { - // for (auto vp : chainVerts) - // { - // creaseVerts[vp] = 1; - // } - // } - // } - // //store crease on V() - - // //this aspect ratio check doesn't work on cadish meshes (long thin triangles spanning whole mesh) - // ForEachFace(m, [&] (FaceType & f) { - // if (vcg::QualityRadii(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr) - // { - // if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) - // f.V(0)->SetS(); - // if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) - // f.V(1)->SetS(); - // if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) - // f.V(2)->SetS(); - // } - // }); - - // ForEachFace(m, [&] (FaceType & f) { - // for (int i = 0; i < 3; ++i) - // { - // if (f.FFp(i) > &f) - // { - // ScalarType angle = fastAngle(NormalizedTriangleNormal(f), NormalizedTriangleNormal(*(f.FFp(i)))); - // if (angle <= params.foldAngleCosThr) - // { - // // if (creaseVerts[vcg::tri::Index(m, f.V0(i))] == 0) - // f.V0(i)->SetS(); - // // if (creaseVerts[vcg::tri::Index(m, f.V1(i))] == 0) - // f.V1(i)->SetS(); - // // if (creaseVerts[vcg::tri::Index(m, f.V2(i))] == 0) - // f.V2(i)->SetS(); - // // if (creaseVerts[vcg::tri::Index(m, f.FFp(i)->V2(f.FFi(i)))] == 0) - // f.FFp(i)->V2(f.FFi(i))->SetS(); - // } - // } - // } - // }); - - return count; - } - - - /* - Edge Swap Step: - This method optimizes the valence of each vertex. - oldDist is the sum of the absolute distance of each vertex from its ideal valence - newDist is the sum of the absolute distance of each vertex from its ideal valence after - the edge swap. - If the swap decreases the total absolute distance, then it's applied, preserving the triangle - quality. +1 - v1 v1 - / \ /|\ - / \ / | \ - / \ / | \ - / _*p\ -1/ | \ -1 - v2--------v0 ========> v2 | v0 - \ / \ | / - \ / \ | / - \ / \ | / - \ / \|/ +1 - v3 v3 - Before Swap After Swap - */ - static bool testSwap(PosType p, ScalarType creaseAngleCosThr) - { - //if border or feature, do not swap - if (/*p.IsBorder() || */p.IsEdgeS()) return false; - - int oldDist = 0, newDist = 0, idealV, actualV; - - PosType tp=p; - - VertexType *v0=tp.V(); - - std::vector incident; - - vcg::face::VVStarVF(tp.V(), incident); - idealV = idealValence(tp); actualV = incident.size(); - oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV - 1)); - - tp.NextF();tp.FlipE();tp.FlipV(); - VertexType *v1=tp.V(); - vcg::face::VVStarVF(tp.V(), incident); - idealV = idealValence(tp); actualV = incident.size(); - oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV + 1)); - - tp.FlipE();tp.FlipV();tp.FlipE(); - VertexType *v2=tp.V(); - vcg::face::VVStarVF(tp.V(), incident); - idealV = idealValence(tp); actualV = incident.size(); - oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV - 1)); - - tp.NextF();tp.FlipE();tp.FlipV(); - VertexType *v3=tp.V(); - vcg::face::VVStarVF(tp.V(), incident); - idealV = idealValence(tp); actualV = incident.size(); - oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV + 1)); - - ScalarType qOld = std::min(Quality(v0->P(),v2->P(),v3->P()),Quality(v0->P(),v1->P(),v2->P())); - ScalarType qNew = std::min(Quality(v0->P(),v1->P(),v3->P()),Quality(v2->P(),v3->P(),v1->P())); - - return (newDist < oldDist && qNew >= qOld * 0.50f) || - (newDist == oldDist && qNew > qOld * 1.f) || qNew > 1.5f * qOld; - } - - static bool checkManifoldness(FaceType & f, int z) - { - PosType pos(&f, (z+2)%3, f.V2(z)); - PosType start = pos; - - do { - pos.FlipE(); - if (!face::IsManifold(*pos.F(), pos.E())) - break; - pos.FlipF(); - } while (pos!=start); - - return pos == start; - } - - // Edge swap step: edges are flipped in order to optimize valence and triangle quality across the mesh - static void ImproveValence(MeshType &m, Params ¶ms) - { - static ScalarType foldCheckRad = math::ToRad(5.); - tri::UpdateTopology::FaceFace(m); - tri::UpdateTopology::VertexFace(m); - ForEachFace(m, [&] (FaceType & f) { -// if (face::IsManifold(f, 0) && face::IsManifold(f, 1) && face::IsManifold(f, 2)) - for (int i = 0; i < 3; ++i) - { - if (&f > f.cFFp(i)) - { - PosType pi(&f, i); - CoordType swapEdgeMidPoint = (f.cP2(i) + f.cFFp(i)->cP2(f.cFFi(i))) / 2.; - std::vector toCheck(1, swapEdgeMidPoint); - - - if(((!params.selectedOnly) || (f.IsS() && f.cFFp(i)->IsS())) && - !face::IsBorder(f, i) && - face::IsManifold(f, i) && /*checkManifoldness(f, i) &&*/ - face::checkFlipEdgeNotManifold(f, i) && - testSwap(pi, params.creaseAngleCosThr) && - (!params.surfDistCheck || testHausdorff(*params.mProject, params.grid, toCheck, params.maxSurfDist)) && - face::CheckFlipEdgeNormal(f, i, vcg::math::ToRad(5.))) - { - //When doing the swap we need to preserve and update the crease info accordingly - FaceType* g = f.cFFp(i); - int w = f.FFi(i); - - bool creaseF = g->IsFaceEdgeS((w + 1) % 3); - bool creaseG = f.IsFaceEdgeS((i + 1) % 3); - - face::FlipEdgeNotManifold(f, i); - - f.ClearFaceEdgeS((i + 1) % 3); - g->ClearFaceEdgeS((w + 1) % 3); - - if (creaseF) - f.SetFaceEdgeS(i); - if (creaseG) - g->SetFaceEdgeS(w); - - ++params.stat.flipNum; - break; - } - } - } - }); - } - - // The predicate that defines which edges should be split - class EdgeSplitAdaptPred - { - public: - int count = 0; - ScalarType length, lengthThr, minQ, maxQ; - bool operator()(PosType &ep) - { - ScalarType mult = math::ClampedLerp((ScalarType)0.5,(ScalarType)1.5, (((math::Abs(ep.V()->Q())+math::Abs(ep.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))); - ScalarType dist = Distance(ep.V()->P(), ep.VFlip()->P()); - if(dist > std::max(mult*length,lengthThr*2)) - { - ++count; - return true; - } - else - return false; - } - }; - - class EdgeSplitLenPred - { - public: - int count = 0; - ScalarType squaredlengthThr; - bool operator()(PosType &ep) - { - if(SquaredDistance(ep.V()->P(), ep.VFlip()->P()) > squaredlengthThr) - { - ++count; - return true; - } - else - return false; - } - }; - - //Split pass: This pass uses the tri::RefineE from the vcglib to implement - //the refinement step, using EdgeSplitPred as a predicate to decide whether to split or not - static void SplitLongEdges(MeshType &m, Params ¶ms) - { - tri::UpdateTopology::FaceFace(m); - tri::MidPoint midFunctor(&m); - - ScalarType minQ,maxQ; - if(params.adapt){ - computeVQualityDistrMinMax(m, minQ, maxQ); - EdgeSplitAdaptPred ep; - ep.minQ = minQ; - ep.maxQ = maxQ; - ep.length = params.maxLength; - ep.lengthThr = params.lengthThr; - tri::RefineE(m,midFunctor,ep); - params.stat.splitNum+=ep.count; - } - else { - EdgeSplitLenPred ep; - ep.squaredlengthThr = params.maxLength*params.maxLength; - tri::RefineMidpoint(m, ep, params.selectedOnly); - params.stat.splitNum+=ep.count; - } - } - - static int VtoE(const int v0, const int v1) - { - static /*constexpr*/ int Vmat[3][3] = { -1, 0, 2, - 0, -1, 1, - 2, 1, -1}; - return Vmat[v0][v1]; - } - - - static bool checkCanMoveOnCollapse(PosType p, std::vector & faces, std::vector & vIdxes, Params ¶ms) - { - bool allIncidentFaceSelected = true; - - PosType pi = p; - - CoordType dEdgeVector = (p.V()->cP() - p.VFlip()->cP()).Normalize(); - - int incidentFeatures = 0; - - for (size_t i = 0; i < faces.size(); ++i) -// if (faces[i] != p.F() && faces[i] != p.FFlip()) - { - if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+1)%3))) - { - incidentFeatures++; - CoordType movingEdgeVector0 = (faces[i]->cP1(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); - if (std::fabs(movingEdgeVector0 * dEdgeVector) < .9f || !p.IsEdgeS()) - return false; - } - if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+2)%3))) - { - incidentFeatures++; - CoordType movingEdgeVector1 = (faces[i]->cP2(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); - if (std::fabs(movingEdgeVector1 * dEdgeVector) < .9f || !p.IsEdgeS()) - return false; - } - allIncidentFaceSelected &= faces[i]->IsS(); - } - - if (incidentFeatures > 4) - return false; - - return params.selectedOnly ? allIncidentFaceSelected : true; - } - - static bool checkFacesAfterCollapse (std::vector & faces, PosType p, const Point3 &mp, Params ¶ms, bool relaxed) - { - for (FaceType* f : faces) - { - if(!(*f).IsD() && f != p.F()) //i'm not a deleted face - { - PosType pi(f, p.V()); //same vertex - - VertexType *v0 = pi.V(); - VertexType *v1 = pi.F()->V1(pi.VInd()); - VertexType *v2 = pi.F()->V2(pi.VInd()); - - if( v1 == p.VFlip() || v2 == p.VFlip()) //i'm the other deleted face - continue; - - //check on new face quality - { - ScalarType newQ = Quality(mp, v1->P(), v2->P()); - ScalarType oldQ = Quality(v0->P(), v1->P(), v2->P()); - - if( newQ <= 0.5*oldQ ) - return false; - } - - // we prevent collapse that makes edges too long (except for cross) - if(!relaxed) - if((Distance(mp, v1->P()) > params.maxLength || Distance(mp, v2->P()) > params.maxLength)) - return false; - - Point3 oldN = NormalizedTriangleNormal(*(pi.F())); - Point3 newN = Normal(mp, v1->P(), v2->P()).Normalize(); - - float div = fastAngle(oldN, newN); - if(div < .0f ) return false; - - // // check on new face distance from original mesh - if (params.surfDistCheck) - { - std::vector points(4); - points[0] = (v1->cP() + v2->cP() + mp) / 3.; - points[1] = (v1->cP() + mp) / 2.; - points[2] = (v2->cP() + mp) / 2.; - points[3] = mp; - if (!testHausdorff(*(params.mProject), params.grid, points, params.maxSurfDist)) - return false; - } - } - } - return true; - } - - - //TODO: Refactor code and implement the correct set up of crease info when collapsing towards a crease edge - static bool checkCollapseFacesAroundVert1(PosType &p, Point3 &mp, Params ¶ms, bool relaxed) - { - PosType p0 = p, p1 = p; - - p1.FlipV(); - - vector vi0, vi1; - vector ff0, ff1; - - face::VFStarVF(p0.V(), ff0, vi0); - face::VFStarVF(p1.V(), ff1, vi1); - - //check crease-moveability - bool moveable0 = checkCanMoveOnCollapse(p0, ff0, vi0, params) && !p0.V()->IsS(); - bool moveable1 = checkCanMoveOnCollapse(p1, ff1, vi1, params) && !p1.V()->IsS(); - - //if both moveable => go to midpoint - // else collapse on movable one - if (!moveable0 && !moveable1) - return false; - - //casting int(true) is always 1 and int(false) = =0 - assert(int(true) == 1); - assert(int(false) == 0); - mp = (p0.V()->cP() * int(moveable1) + p1.V()->cP() * int(moveable0)) / (int(moveable0) + int(moveable1)); - - if (!moveable0) - p = p0; - else - p = p1; - - if (checkFacesAfterCollapse(ff0, p0, mp, params, relaxed)) - return checkFacesAfterCollapse(ff1, p1, mp, params, relaxed); - - return false; - } - - static bool testCollapse1(PosType &p, Point3 &mp, ScalarType minQ, ScalarType maxQ, Params ¶ms, bool relaxed = false) - { - ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.5,(ScalarType)1.5, (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))) : (ScalarType)1; - ScalarType dist = Distance(p.V()->P(), p.VFlip()->P()); - ScalarType thr = mult*params.minLength; - ScalarType area = DoubleArea(*(p.F()))/2.f; - if(relaxed || (dist < thr || area < params.minLength*params.minLength/100.f))//if to collapse - { - return checkCollapseFacesAroundVert1(p, mp, params, relaxed); - } - return false; - } - - //This function is especially useful to enforce feature preservation during collapses - //of boundary edges in planar or near planar section of the mesh - static bool chooseBoundaryCollapse(PosType &p, VertexPair &pair) - { - Point3 collapseNV, collapsedNV0, collapsedNV1; - collapseNV = (p.V()->P() - p.VFlip()->P()).normalized(); - - vector vv; - face::VVStarVF(p.V(), vv); - - for(VertexType *v: vv) - if(!(*v).IsD() && (*v).IsB() && v != p.VFlip()) //ignore non border - collapsedNV0 = ((*v).P() - p.VFlip()->P()).normalized(); //edge vector after collapse - - face::VVStarVF(p.VFlip(), vv); - - for(VertexType *v: vv) - if(!(*v).IsD() && (*v).IsB() && v != p.V()) //ignore non border - collapsedNV1 = ((*v).P() - p.V()->P()).normalized(); //edge vector after collapse - - float cosine = cos(math::ToRad(1.5f)); - float angle0 = fabs(fastAngle(collapseNV, collapsedNV0)); - float angle1 = fabs(fastAngle(collapseNV, collapsedNV1)); - //if on both sides we deviate too much after collapse => don't collapse - if(angle0 <= cosine && angle1 <= cosine) - return false; - //choose the best collapse (the more parallel one to the previous edge..) - pair = (angle0 >= angle1) ? VertexPair(p.V(), p.VFlip()) : VertexPair(p.VFlip(), p.V()); - return true; - } - - //The actual collapse step: foreach edge it is collapse iff TestCollapse returns true AND - // the linkConditions are preserved - static void CollapseShortEdges(MeshType &m, Params ¶ms) - { - ScalarType minQ, maxQ; - int candidates = 0; - - if(params.adapt) - computeVQualityDistrMinMax(m, minQ, maxQ); - - tri::UpdateTopology::VertexFace(m); - tri::UpdateFlags::FaceBorderFromVF(m); - tri::UpdateFlags::VertexBorderFromFaceBorder(m); - - SelectionStack ss(m); - ss.push(); - - { - tri::UpdateTopology::FaceFace(m); - Clean::CountNonManifoldVertexFF(m,true); - - //FROM NOW ON VSelection is NotManifold - - for(auto fi=m.face.begin(); fi!=m.face.end(); ++fi) - if(!(*fi).IsD() && (params.selectedOnly == false || fi->IsS())) - { - for(auto i=0; i<3; ++i) - { - PosType pi(&*fi, i); - ++candidates; - VertexPair bp = VertexPair(pi.V(), pi.VFlip()); - Point3 mp = (pi.V()->P()+pi.VFlip()->P())/2.f; - - if(testCollapse1(pi, mp, minQ, maxQ, params) && Collapser::LinkConditions(bp)) - { - //collapsing on pi.V() - bp = VertexPair(pi.VFlip(), pi.V()); - - Collapser::Do(m, bp, mp, true); - ++params.stat.collapseNum; - break; - } - - } - } - } - - ss.pop(); - } - - - //Here I just need to check the faces of the cross, since the other faces are not - //affected by the collapse of the internal faces of the cross. - static bool testCrossCollapse(PosType &p, std::vector ff, std::vector vi, Point3 &mp, Params ¶ms) - { - if(!checkFacesAfterCollapse(ff, p, mp, params, true)) - return false; - return true; - } - - /* - *Choose the best way to collapse a cross based on the (external) cross vertices valence - *and resulting face quality - * +0 -1 - * v1 v1 v1 - * /| \ /|\ / \ - * / | \ / | \ / \ - * / | \ / | \ / \ - * / *p| \ -1/ | \ -1 +0/ \+0 - * v0-------- v2 ========> v0 | v2 OR v0-------v2 - * \ | / \ | / \ / - * \ | / \ | / \ / - * \ | / \ | / \ / - * \ | / \|/ +0 \ / -1 - * v3 v3 v3 - */ - static bool chooseBestCrossCollapse(PosType &p, VertexPair& bp, vector &ff) - { - vector vv0, vv1, vv2, vv3; - VertexType *v0, *v1, *v2, *v3; - - v0 = p.F()->V1(p.VInd()); - v1 = p.F()->V2(p.VInd()); - - - bool crease[4] = {false, false, false, false}; - - crease[0] = p.F()->IsFaceEdgeS(VtoE(p.VInd(), (p.VInd()+1)%3)); - crease[1] = p.F()->IsFaceEdgeS(VtoE(p.VInd(), (p.VInd()+2)%3)); - - for(FaceType *f: ff) - if(!(*f).IsD() && f != p.F()) - { - PosType pi(f, p.V()); - VertexType *fv1 = pi.F()->V1(pi.VInd()); - VertexType *fv2 = pi.F()->V2(pi.VInd()); - - if(fv1 == v0 || fv2 == v0) - { - if (fv1 == 0) - { - v3 = fv2; - crease[3] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+2)%3)); - } - else - { - v3 = fv1; - crease[3] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+1)%3)); - } - // v3 = (fv1 == v0) ? fv2 : fv1; - } - - if(fv1 == v1 || fv2 == v1) - { - if (fv1 == v1) - { - v2 = fv2; - crease[2] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+2)%3)); - } - else - { - v2 = fv1; - crease[2] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+1)%3)); - } - // v2 = (fv1 == v1) ? fv2 : fv1; - } - } - - face::VVStarVF(v0, vv0); - face::VVStarVF(v1, vv1); - face::VVStarVF(v2, vv2); - face::VVStarVF(v3, vv3); - - int nv0 = vv0.size(), nv1 = vv1.size(); - int nv2 = vv2.size(), nv3 = vv3.size(); - - int delta1 = (idealValence(*v0) - nv0) + (idealValence(*v2) - nv2); - int delta2 = (idealValence(*v1) - nv1) + (idealValence(*v3) - nv3); - - ScalarType Q1 = std::min(Quality(v0->P(), v1->P(), v3->P()), Quality(v1->P(), v2->P(), v3->P())); - ScalarType Q2 = std::min(Quality(v0->P(), v1->P(), v2->P()), Quality(v2->P(), v3->P(), v0->P())); - - if (crease[0] || crease[1] || crease[2] || crease[3]) - return false; - // if (crease[0] && crease[1] && crease[2] && crease[3]) - // { - // return false; - // } - - // if (crease[0] || crease[2]) - // { - // bp = VertexPair(p.V(), v0); - // return true; - // } - - // if (crease[1] || crease[3]) - // { - // bp = VertexPair(p.V(), v1); - // return true; - // } - - //no crease - if(delta1 < delta2 && Q1 >= 0.6f*Q2) - { - bp = VertexPair(p.V(), v1); - return true; - } - else - { - bp = VertexPair(p.V(), v0); - return true; - } - } - //Cross Collapse pass: This pass cleans the mesh from cross vertices, keeping in mind the link conditions - //and feature preservations tests. - static void CollapseCrosses(MeshType &m , Params ¶ms) - { - tri::UpdateTopology::VertexFace(m); - tri::UpdateFlags::VertexBorderFromNone(m); - int count = 0; - - SelectionStack ss(m); - ss.push(); - - - { - tri::UpdateTopology::FaceFace(m); - Clean::CountNonManifoldVertexFF(m,true); - - //From now on Selection on vertices is not manifoldness - - for(auto fi=m.face.begin(); fi!=m.face.end(); ++fi) - if(!(*fi).IsD() && (!params.selectedOnly || fi->IsS())) - { - for(auto i=0; i<3; ++i) - { - PosType pi(&*fi, i); - if(!pi.V()->IsB()) - { - vector ff; - vector vi; - face::VFStarVF(pi.V(), ff, vi); - - //if cross need to check what creases you have and decide where to collapse accordingly - //if tricuspidis need whenever you have at least one crease => can't collapse anywhere - if(ff.size() == 4 || ff.size() == 3) - { - // VertexPair bp; - VertexPair bp = VertexPair(pi.V(), pi.VFlip()); - Point3 mp = (pi.V()->P()+pi.VFlip()->P())/2.f; - - if(testCollapse1(pi, mp, 0, 0, params, true) && Collapser::LinkConditions(bp)) - { - bp = VertexPair(pi.VFlip(), pi.V()); - Collapser::Do(m, bp, mp, true); - ++params.stat.collapseNum; - ++count; - break; - } - } - } - } - } - } - - ss.pop(); - Allocator::CompactEveryVector(m); - } - - // This function sets the selection bit on vertices that lie on creases - static int selectVertexFromCrease(MeshType &m, ScalarType creaseThr) - { - int count = 0; - Clean::CountNonManifoldVertexFF(m, true, false); - - ForEachFacePos(m, [&](PosType &p){ - if(p.IsBorder() || p.IsEdgeS()/*testCreaseEdge(p, creaseThr)*/) - { - p.V()->SetS(); - p.VFlip()->SetS(); - ++count; - } - }); - return count; - } - - static int selectVertexFromFold(MeshType &m, Params & params) - { - std::vector creaseVerts(m.VN(), 0); - ForEachFacePos(m, [&] (PosType & p) { - if (p.IsEdgeS()) - { - creaseVerts[vcg::tri::Index(m, p.V())] = 1; - creaseVerts[vcg::tri::Index(m, p.VFlip())] = 1; - } - }); - - - //this aspect ratio check doesn't work on cadish meshes (long thin triangles spanning whole mesh) - ForEachFace(m, [&] (FaceType & f) { - if (vcg::Quality(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr || vcg::DoubleArea(f) < 0.00001) - { - if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) - f.V(0)->SetS(); - if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) - f.V(1)->SetS(); - if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) - f.V(2)->SetS(); - } - }); - - - ForEachFace(m, [&] (FaceType & f) { - for (int i = 0; i < 3; ++i) - { - if (f.FFp(i) > &f) - { - ScalarType angle = fastAngle(NormalizedTriangleNormal(f), NormalizedTriangleNormal(*(f.FFp(i)))); - if (angle <= params.foldAngleCosThr) - { - if (creaseVerts[vcg::tri::Index(m, f.V0(i))] == 0) - f.V0(i)->SetS(); - if (creaseVerts[vcg::tri::Index(m, f.V1(i))] == 0) - f.V1(i)->SetS(); - if (creaseVerts[vcg::tri::Index(m, f.V2(i))] == 0) - f.V2(i)->SetS(); - if (creaseVerts[vcg::tri::Index(m, f.FFp(i)->V2(f.FFi(i)))] == 0) - f.FFp(i)->V2(f.FFi(i))->SetS(); - } - } - } - }); - - return 0; - } - - - - - static void FoldRelax(MeshType &m, Params params, const int step, const bool strict = true) - { - typename vcg::tri::Smooth::LaplacianInfo lpz(CoordType(0, 0, 0), 0); - SimpleTempData::LaplacianInfo> TD(m.vert, lpz); - const ScalarType maxDist = (strict) ? params.maxSurfDist / 1000. : params.maxSurfDist; - for (int i = 0; i < step; ++i) - { - TD.Init(lpz); - vcg::tri::Smooth::AccumulateLaplacianInfo(m, TD, false); - - for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) - { - std::vector newPos(4); - bool moving = false; - - for (int j = 0; j < 3; ++j) - { - newPos[j] = fi->cP(j); - if (!fi->V(j)->IsD() && TD[fi->V(j)].cnt > 0) - { - if (fi->V(j)->IsS()) - { - newPos[j] = (fi->V(j)->P() + TD[fi->V(j)].sum) / (TD[fi->V(j)].cnt + 1); - moving = true; - } - } - } - - if (moving) - { -// const CoordType oldN = vcg::NormalizedTriangleNormal(*fi); -// const CoordType newN = vcg::Normal(newPos[0], newPos[1], newPos[2]).Normalize(); - - newPos[3] = (newPos[0] + newPos[1] + newPos[2]) / 3.; - if (/*(strict || oldN * newN > 0.99) &&*/ (!params.surfDistCheck || testHausdorff(*params.mProject, params.grid, newPos, maxDist))) - { - for (int j = 0; j < 3; ++j) - fi->V(j)->P() = newPos[j]; - } - } - } - } - } - - static void VertexCoordPlanarLaplacian(MeshType &m, Params & params, int step, ScalarType delta = 0.2) - { - typename vcg::tri::Smooth::LaplacianInfo lpz(CoordType(0, 0, 0), 0); - SimpleTempData::LaplacianInfo> TD(m.vert, lpz); - for (int i = 0; i < step; ++i) - { - TD.Init(lpz); - vcg::tri::Smooth::AccumulateLaplacianInfo(m, TD, false); - // First normalize the AccumulateLaplacianInfo - for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if (!(*vi).IsD() && TD[*vi].cnt > 0) - { - if ((*vi).IsS()) - TD[*vi].sum = ((*vi).P() + TD[*vi].sum) / (TD[*vi].cnt + 1); - } - - for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) - { - if (!(*fi).IsD()) - { - for (int j = 0; j < 3; ++j) - { - if (Angle(Normal(TD[(*fi).V0(j)].sum, (*fi).P1(j), (*fi).P2(j)), - Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) - TD[(*fi).V0(j)].sum = (*fi).P0(j); - } - } - } - for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) - { - if (!(*fi).IsD()) - { - for (int j = 0; j < 3; ++j) - { - if (Angle(Normal(TD[(*fi).V0(j)].sum, TD[(*fi).V1(j)].sum, (*fi).P2(j)), - Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) - { - TD[(*fi).V0(j)].sum = (*fi).P0(j); - TD[(*fi).V1(j)].sum = (*fi).P1(j); - } - } - } - } - - for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if (!(*vi).IsD() && TD[*vi].cnt > 0) - { - std::vector newPos(1, TD[*vi].sum); - if ((*vi).IsS() && testHausdorff(*params.mProject, params.grid, newPos, params.maxSurfDist)) - (*vi).P() = (*vi).P() * (1-delta) + TD[*vi].sum * (delta); - } - } // end step - } - - // static int - /** - * Simple Laplacian Smoothing step - * Border and crease vertices are kept fixed. - * If there are selected faces and the param.onlySelected is true we compute - * the set of internal vertices to the selection and we combine it in and with - * the vertexes not on border or creases - */ - static void ImproveByLaplacian(MeshType &m, Params params) - { - SelectionStack ss(m); - - if(params.selectedOnly) { - ss.push(); - tri::UpdateSelection::VertexFromFaceStrict(m); - ss.push(); - } - tri::UpdateTopology::FaceFace(m); - tri::UpdateFlags::VertexBorderFromFaceAdj(m); - tri::UpdateSelection::VertexFromBorderFlag(m); - selectVertexFromCrease(m, params.creaseAngleCosThr); - tri::UpdateSelection::VertexInvert(m); - if(params.selectedOnly) { - ss.popAnd(); - } - - VertexCoordPlanarLaplacian(m, params, 1); - - tri::UpdateSelection::VertexClear(m); - - selectVertexFromFold(m, params); - FoldRelax(m, params, 2); - - tri::UpdateSelection::VertexClear(m); - - if(params.selectedOnly) { - ss.pop(); - } - } - /* - Reprojection step, this method reprojects each vertex on the original surface - sampling the nearest Point3 onto it using a uniform grid StaticGrid t - */ - //TODO: improve crease reprojection: - // crease verts should reproject only on creases. - static void ProjectToSurface(MeshType &m, Params & params) - { - for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) - if(!(*vi).IsD()) - { - Point3 newP, normP, barP; - ScalarType maxDist = params.maxSurfDist * 1.5f, minDist = 0.f; - FaceType* fp = GetClosestFaceBase(*params.mProject, params.grid, vi->cP(), maxDist, minDist, newP, normP, barP); - - if (fp != NULL) - { - vi->P() = newP; - } - } - } + /* + TODO: Add better crease support: detect all creases at starting time, saving it on facedgesel flags + All operations must then preserve the faceedgesel flag accordingly: + Refinement -> Check that refiner propagates faceedgesel [should be doing it] + Collapse -> Implement 1D edge collapse and better check on corners and creases + Swap -> Totally avoid swapping crease edges [ok] + Smooth -> Apply 1D smoothing to crease vertices + check on + (http://www.cs.ubc.ca/labs/imager/tr/2009/eltopo/sisc2009.pdf) + */ + IsotropicRemeshing() {} + // this returns the value of cos(a) where a is the angle between n0 and n1. (scalar prod is cos(a)) + static inline ScalarType fastAngle(Point3 n0, Point3 n1) + { + return math::Clamp(n0*n1,(ScalarType)-1.0,(ScalarType)1.0); + } + // compare the value of the scalar prod with the cos of the crease threshold + static inline bool testCreaseEdge(PosType &p, ScalarType creaseCosineThr) + { + ScalarType angle = fastAngle(NormalizedTriangleNormal(*(p.F())), NormalizedTriangleNormal(*(p.FFlip()))); + return angle <= creaseCosineThr && angle >= -0.98; + // return (angle <= creaseCosineThr && angle >= -creaseCosineThr); + } + // this stores in minQ the value of the 10th percentile of the VertQuality distribution and in + // maxQ the value of the 90th percentile. + static inline void computeVQualityDistrMinMax(MeshType &m, ScalarType &minQ, ScalarType &maxQ) + { + Distribution distr; + tri::Stat::ComputePerVertexQualityDistribution(m,distr); + + maxQ = distr.Percentile(0.9f); + minQ = distr.Percentile(0.1f); + } + + //Computes PerVertexQuality as a function of the 'deviation' of the normals taken from + //the faces incident to each vertex + static void computeQuality(MeshType &m) + { + tri::RequirePerVertexQuality(m); + tri::UpdateFlags::VertexClearV(m); + + for(auto vi=m.vert.begin(); vi!=m.vert.end(); ++vi) + if(!(*vi).IsD()) + { + vector ff; + face::VFExtendedStarVF(&*vi, 0, ff); + + ScalarType tot = 0.f; + auto it = ff.begin(); + Point3 fNormal = NormalizedTriangleNormal(**it); + ++it; + while(it != ff.end()) + { + tot+= 1-math::Abs(fastAngle(fNormal, NormalizedTriangleNormal(**it))); + ++it; + } + vi->Q() = tot / (ScalarType)(std::max(1, ((int)ff.size()-1))); + vi->SetV(); + } + } + + /* + Computes the ideal valence for the vertex in pos p: + 4 for border vertices + 6 for internal vertices + */ + static inline int idealValence(PosType &p) + { + if(p.IsBorder()) return 4; + return 6; + } + static inline int idealValence(VertexType &v) + { + if(v.IsB()) return 4; + return 6; + } + static inline int idealValenceSlow(PosType &p) + { + std::vector posVec; + VFOrderedStarFF(p,posVec); + float angleSumRad =0; + for(PosType &ip : posVec) + { + angleSumRad += ip.AngleRad(); + } + + return (int)(std::ceil(angleSumRad / (M_PI/3.0f))); + } + + static bool testHausdorff (MeshType & m, StaticGrid & grid, const std::vector & verts, const ScalarType maxD, const CoordType checkOrientation = CoordType(0,0,0)) + { + for (CoordType v : verts) + { + CoordType closest, normal, ip; + ScalarType dist = 0; + FaceType* fp = GetClosestFaceBase(m, grid, v, maxD, dist, closest); + + //you can't use this kind of orientation check, since when you stand on edges it fails + if (fp == NULL /*|| (checkOrientation != CoordType(0,0,0) && checkOrientation * fp->N() < 0.5)*/) + { + return false; + } + } + return true; + } + + static int tagCreaseEdges(MeshType &m, Params & params) + { + int count = 0; + std::vector creaseVerts(m.VN(), 0); + + vcg::tri::UpdateFlags::VertexClearV(m); + std::queue creaseQueue; + ForEachFacePos(m, [&](PosType &p){ + + if (p.IsBorder()) + p.F()->SetFaceEdgeS(p.E()); + + // if((p.FFlip() > p.F())) + { + FaceType *ff = p.F(); + FaceType *ffAdj = p.FFlip(); + + double quality = vcg::QualityRadii(ff->cP(0), ff->cP(1), ff->cP(2)); + double qualityAdj = vcg::QualityRadii(ffAdj->cP(0), ffAdj->cP(1), ffAdj->cP(2)); + + bool qualityCheck = quality > 0.00000001 && qualityAdj > 0.00000001; + // bool areaCheck = vcg::DoubleArea(*ff) > 0.000001 && vcg::DoubleArea(*ffAdj) > 0.000001; + + if (!params.userSelectedCreases && (testCreaseEdge(p, params.creaseAngleCosThr) /*&& areaCheck*//* && qualityCheck*/) || p.IsBorder()) + { + PosType pp = p; + do { + pp.F()->SetFaceEdgeS(pp.E()); + pp.NextF(); + } while (pp != p); + + creaseQueue.push(p); + } + } + }); + + // //now all creases are checked... + // //prune false positive (too small) (count + scale?) + + // while (!creaseQueue.empty()) + // { + // PosType & p = creaseQueue.front(); + // creaseQueue.pop(); + + // std::stack chainQueue; + // std::vector chainVerts; + + // if (!p.V()->IsV()) + // { + // chainQueue.push(p); + // } + + // p.FlipV(); + // p.NextEdgeS(); + + // if (!p.V()->IsV()) + // { + // chainQueue.push(p); + // } + + // while (!chainQueue.empty()) + // { + // PosType p = chainQueue.top(); + // chainQueue.pop(); + + // p.V()->SetV(); + // chainVerts.push_back(vcg::tri::Index(m, p.V())); + + // PosType pp = p; + + // //circle around vert in search for new crease edges + // do { + // pp.NextF(); //jump adj face + // pp.FlipE(); // this edge is already ok => jump to next + // if (pp.IsEdgeS()) + // { + // PosType nextPos = pp; + // nextPos.FlipV(); // go to next vert in the chain + // if (!nextPos.V()->IsV()) // if already visited...ignore + // { + // chainQueue.push(nextPos); + // } + // } + // } + // while (pp != p); + + // } + + // if (chainVerts.size() > 5) + // { + // for (auto vp : chainVerts) + // { + // creaseVerts[vp] = 1; + // } + // } + // } + // //store crease on V() + + // //this aspect ratio check doesn't work on cadish meshes (long thin triangles spanning whole mesh) + // ForEachFace(m, [&] (FaceType & f) { + // if (vcg::QualityRadii(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr) + // { + // if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) + // f.V(0)->SetS(); + // if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) + // f.V(1)->SetS(); + // if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) + // f.V(2)->SetS(); + // } + // }); + + // ForEachFace(m, [&] (FaceType & f) { + // for (int i = 0; i < 3; ++i) + // { + // if (f.FFp(i) > &f) + // { + // ScalarType angle = fastAngle(NormalizedTriangleNormal(f), NormalizedTriangleNormal(*(f.FFp(i)))); + // if (angle <= params.foldAngleCosThr) + // { + // // if (creaseVerts[vcg::tri::Index(m, f.V0(i))] == 0) + // f.V0(i)->SetS(); + // // if (creaseVerts[vcg::tri::Index(m, f.V1(i))] == 0) + // f.V1(i)->SetS(); + // // if (creaseVerts[vcg::tri::Index(m, f.V2(i))] == 0) + // f.V2(i)->SetS(); + // // if (creaseVerts[vcg::tri::Index(m, f.FFp(i)->V2(f.FFi(i)))] == 0) + // f.FFp(i)->V2(f.FFi(i))->SetS(); + // } + // } + // } + // }); + + return count; + } + + + /* + Edge Swap Step: + This method optimizes the valence of each vertex. + oldDist is the sum of the absolute distance of each vertex from its ideal valence + newDist is the sum of the absolute distance of each vertex from its ideal valence after + the edge swap. + If the swap decreases the total absolute distance, then it's applied, preserving the triangle + quality. +1 + v1 v1 + / \ /|\ + / \ / | \ + / \ / | \ + / _*p\ -1/ | \ -1 + v2--------v0 ========> v2 | v0 + \ / \ | / + \ / \ | / + \ / \ | / + \ / \|/ +1 + v3 v3 + Before Swap After Swap + */ + static bool testSwap(PosType p, ScalarType creaseAngleCosThr) + { + //if border or feature, do not swap + if (/*p.IsBorder() || */p.IsEdgeS()) return false; + + int oldDist = 0, newDist = 0, idealV, actualV; + + PosType tp=p; + + VertexType *v0=tp.V(); + + std::vector incident; + + vcg::face::VVStarVF(tp.V(), incident); + idealV = idealValence(tp); actualV = incident.size(); + oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV - 1)); + + tp.NextF();tp.FlipE();tp.FlipV(); + VertexType *v1=tp.V(); + vcg::face::VVStarVF(tp.V(), incident); + idealV = idealValence(tp); actualV = incident.size(); + oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV + 1)); + + tp.FlipE();tp.FlipV();tp.FlipE(); + VertexType *v2=tp.V(); + vcg::face::VVStarVF(tp.V(), incident); + idealV = idealValence(tp); actualV = incident.size(); + oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV - 1)); + + tp.NextF();tp.FlipE();tp.FlipV(); + VertexType *v3=tp.V(); + vcg::face::VVStarVF(tp.V(), incident); + idealV = idealValence(tp); actualV = incident.size(); + oldDist += abs(idealV - actualV); newDist += abs(idealV - (actualV + 1)); + + ScalarType qOld = std::min(Quality(v0->P(),v2->P(),v3->P()),Quality(v0->P(),v1->P(),v2->P())); + ScalarType qNew = std::min(Quality(v0->P(),v1->P(),v3->P()),Quality(v2->P(),v3->P(),v1->P())); + + return (newDist < oldDist && qNew >= qOld * 0.50f) || + (newDist == oldDist && qNew > qOld * 1.f) || qNew > 1.5f * qOld; + } + + static bool checkManifoldness(FaceType & f, int z) + { + PosType pos(&f, (z+2)%3, f.V2(z)); + PosType start = pos; + + do { + pos.FlipE(); + if (!face::IsManifold(*pos.F(), pos.E())) + break; + pos.FlipF(); + } while (pos!=start); + + return pos == start; + } + + // Edge swap step: edges are flipped in order to optimize valence and triangle quality across the mesh + static void ImproveValence(MeshType &m, Params ¶ms) + { + static ScalarType foldCheckRad = math::ToRad(5.); + tri::UpdateTopology::FaceFace(m); + tri::UpdateTopology::VertexFace(m); + ForEachFace(m, [&] (FaceType & f) { + // if (face::IsManifold(f, 0) && face::IsManifold(f, 1) && face::IsManifold(f, 2)) + for (int i = 0; i < 3; ++i) + { + if (&f > f.cFFp(i)) + { + PosType pi(&f, i); + CoordType swapEdgeMidPoint = (f.cP2(i) + f.cFFp(i)->cP2(f.cFFi(i))) / 2.; + std::vector toCheck(1, swapEdgeMidPoint); + + + if(((!params.selectedOnly) || (f.IsS() && f.cFFp(i)->IsS())) && + !face::IsBorder(f, i) && + face::IsManifold(f, i) && /*checkManifoldness(f, i) &&*/ + face::checkFlipEdgeNotManifold(f, i) && + testSwap(pi, params.creaseAngleCosThr) && + (!params.surfDistCheck || testHausdorff(*params.mProject, params.grid, toCheck, params.maxSurfDist)) && + face::CheckFlipEdgeNormal(f, i, vcg::math::ToRad(5.))) + { + //When doing the swap we need to preserve and update the crease info accordingly + FaceType* g = f.cFFp(i); + int w = f.FFi(i); + + bool creaseF = g->IsFaceEdgeS((w + 1) % 3); + bool creaseG = f.IsFaceEdgeS((i + 1) % 3); + + face::FlipEdgeNotManifold(f, i); + + f.ClearFaceEdgeS((i + 1) % 3); + g->ClearFaceEdgeS((w + 1) % 3); + + if (creaseF) + f.SetFaceEdgeS(i); + if (creaseG) + g->SetFaceEdgeS(w); + + ++params.stat.flipNum; + break; + } + } + } + }); + } + + // The predicate that defines which edges should be split + class EdgeSplitAdaptPred + { + public: + int count = 0; + ScalarType length, lengthThr, minQ, maxQ; + bool operator()(PosType &ep) + { + ScalarType mult = math::ClampedLerp((ScalarType)0.5,(ScalarType)1.5, (((math::Abs(ep.V()->Q())+math::Abs(ep.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))); + ScalarType dist = Distance(ep.V()->P(), ep.VFlip()->P()); + if(dist > std::max(mult*length,lengthThr*2)) + { + ++count; + return true; + } + else + return false; + } + }; + + class EdgeSplitLenPred + { + public: + int count = 0; + ScalarType squaredlengthThr; + bool operator()(PosType &ep) + { + if(SquaredDistance(ep.V()->P(), ep.VFlip()->P()) > squaredlengthThr) + { + ++count; + return true; + } + else + return false; + } + }; + + //Split pass: This pass uses the tri::RefineE from the vcglib to implement + //the refinement step, using EdgeSplitPred as a predicate to decide whether to split or not + static void SplitLongEdges(MeshType &m, Params ¶ms) + { + tri::UpdateTopology::FaceFace(m); + tri::MidPoint midFunctor(&m); + + ScalarType minQ,maxQ; + if(params.adapt){ + computeVQualityDistrMinMax(m, minQ, maxQ); + EdgeSplitAdaptPred ep; + ep.minQ = minQ; + ep.maxQ = maxQ; + ep.length = params.maxLength; + ep.lengthThr = params.lengthThr; + tri::RefineE(m,midFunctor,ep); + params.stat.splitNum+=ep.count; + } + else { + EdgeSplitLenPred ep; + ep.squaredlengthThr = params.maxLength*params.maxLength; + tri::RefineMidpoint(m, ep, params.selectedOnly); + params.stat.splitNum+=ep.count; + } + } + + static int VtoE(const int v0, const int v1) + { + static /*constexpr*/ int Vmat[3][3] = { -1, 0, 2, + 0, -1, 1, + 2, 1, -1}; + return Vmat[v0][v1]; + } + + + static bool checkCanMoveOnCollapse(PosType p, std::vector & faces, std::vector & vIdxes, Params ¶ms) + { + bool allIncidentFaceSelected = true; + + PosType pi = p; + + CoordType dEdgeVector = (p.V()->cP() - p.VFlip()->cP()).Normalize(); + + int incidentFeatures = 0; + + for (size_t i = 0; i < faces.size(); ++i) + // if (faces[i] != p.F() && faces[i] != p.FFlip()) + { + if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+1)%3))) + { + incidentFeatures++; + CoordType movingEdgeVector0 = (faces[i]->cP1(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); + if (std::fabs(movingEdgeVector0 * dEdgeVector) < .9f || !p.IsEdgeS()) + return false; + } + if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+2)%3))) + { + incidentFeatures++; + CoordType movingEdgeVector1 = (faces[i]->cP2(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); + if (std::fabs(movingEdgeVector1 * dEdgeVector) < .9f || !p.IsEdgeS()) + return false; + } + allIncidentFaceSelected &= faces[i]->IsS(); + } + + if (incidentFeatures > 4) + return false; + + return params.selectedOnly ? allIncidentFaceSelected : true; + } + + static bool checkFacesAfterCollapse (std::vector & faces, PosType p, const Point3 &mp, Params ¶ms, bool relaxed) + { + for (FaceType* f : faces) + { + if(!(*f).IsD() && f != p.F()) //i'm not a deleted face + { + PosType pi(f, p.V()); //same vertex + + VertexType *v0 = pi.V(); + VertexType *v1 = pi.F()->V1(pi.VInd()); + VertexType *v2 = pi.F()->V2(pi.VInd()); + + if( v1 == p.VFlip() || v2 == p.VFlip()) //i'm the other deleted face + continue; + + //check on new face quality + { + ScalarType newQ = Quality(mp, v1->P(), v2->P()); + ScalarType oldQ = Quality(v0->P(), v1->P(), v2->P()); + + if(newQ <= 0.5*oldQ) + return false; + } + + // we prevent collapse that makes edges too long (except for cross) + if(!relaxed) + if((Distance(mp, v1->P()) > params.maxLength || Distance(mp, v2->P()) > params.maxLength)) + return false; + + Point3 oldN = NormalizedTriangleNormal(*(pi.F())); + Point3 newN = Normal(mp, v1->P(), v2->P()).Normalize(); + +// float div = fastAngle(oldN, newN); +// if(div < .9f ) return false; + if (oldN * newN < 0.8f) + return false; + + // // check on new face distance from original mesh + if (params.surfDistCheck) + { + std::vector points(4); + points[0] = (v1->cP() + v2->cP() + mp) / 3.; + points[1] = (v1->cP() + mp) / 2.; + points[2] = (v2->cP() + mp) / 2.; + points[3] = mp; + if (!testHausdorff(*(params.mProject), params.grid, points, params.maxSurfDist, newN)) + return false; + } + } + } + return true; + } + + + //TODO: Refactor code and implement the correct set up of crease info when collapsing towards a crease edge + static bool checkCollapseFacesAroundVert1(PosType &p, Point3 &mp, Params ¶ms, bool relaxed) + { + PosType p0 = p, p1 = p; + + p1.FlipV(); + + vector vi0, vi1; + vector ff0, ff1; + + face::VFStarVF(p0.V(), ff0, vi0); + face::VFStarVF(p1.V(), ff1, vi1); + + //check crease-moveability + bool moveable0 = checkCanMoveOnCollapse(p0, ff0, vi0, params) && !p0.V()->IsS(); + bool moveable1 = checkCanMoveOnCollapse(p1, ff1, vi1, params) && !p1.V()->IsS(); + + //if both moveable => go to midpoint + // else collapse on movable one + if (!moveable0 && !moveable1) + return false; + + //casting int(true) is always 1 and int(false) = =0 + assert(int(true) == 1); + assert(int(false) == 0); + mp = (p0.V()->cP() * int(moveable1) + p1.V()->cP() * int(moveable0)) / (int(moveable0) + int(moveable1)); + + if (checkFacesAfterCollapse(ff0, p0, mp, params, relaxed)) + return checkFacesAfterCollapse(ff1, p1, mp, params, relaxed); + + return false; + } + + static bool testCollapse1(PosType &p, Point3 &mp, ScalarType minQ, ScalarType maxQ, Params ¶ms, bool relaxed = false) + { + ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.5,(ScalarType)1.5, (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))) : (ScalarType)1; + ScalarType dist = Distance(p.V()->P(), p.VFlip()->P()); + ScalarType thr = mult*params.minLength; + ScalarType area = DoubleArea(*(p.F()))/2.f; + if(relaxed || (dist < thr || area < params.minLength*params.minLength/100.f))//if to collapse + { + return checkCollapseFacesAroundVert1(p, mp, params, relaxed); + } + return false; + } + + //This function is especially useful to enforce feature preservation during collapses + //of boundary edges in planar or near planar section of the mesh + static bool chooseBoundaryCollapse(PosType &p, VertexPair &pair) + { + Point3 collapseNV, collapsedNV0, collapsedNV1; + collapseNV = (p.V()->P() - p.VFlip()->P()).normalized(); + + vector vv; + face::VVStarVF(p.V(), vv); + + for(VertexType *v: vv) + if(!(*v).IsD() && (*v).IsB() && v != p.VFlip()) //ignore non border + collapsedNV0 = ((*v).P() - p.VFlip()->P()).normalized(); //edge vector after collapse + + face::VVStarVF(p.VFlip(), vv); + + for(VertexType *v: vv) + if(!(*v).IsD() && (*v).IsB() && v != p.V()) //ignore non border + collapsedNV1 = ((*v).P() - p.V()->P()).normalized(); //edge vector after collapse + + float cosine = cos(math::ToRad(1.5f)); + float angle0 = fabs(fastAngle(collapseNV, collapsedNV0)); + float angle1 = fabs(fastAngle(collapseNV, collapsedNV1)); + //if on both sides we deviate too much after collapse => don't collapse + if(angle0 <= cosine && angle1 <= cosine) + return false; + //choose the best collapse (the more parallel one to the previous edge..) + pair = (angle0 >= angle1) ? VertexPair(p.V(), p.VFlip()) : VertexPair(p.VFlip(), p.V()); + return true; + } + + //The actual collapse step: foreach edge it is collapse iff TestCollapse returns true AND + // the linkConditions are preserved + static void CollapseShortEdges(MeshType &m, Params ¶ms) + { + ScalarType minQ, maxQ; + int candidates = 0; + + if(params.adapt) + computeVQualityDistrMinMax(m, minQ, maxQ); + + tri::UpdateTopology::VertexFace(m); + tri::UpdateFlags::FaceBorderFromVF(m); + tri::UpdateFlags::VertexBorderFromFaceBorder(m); + + SelectionStack ss(m); + ss.push(); + + { + tri::UpdateTopology::FaceFace(m); + Clean::CountNonManifoldVertexFF(m,true); + + //FROM NOW ON VSelection is NotManifold + + for(auto fi=m.face.begin(); fi!=m.face.end(); ++fi) + if(!(*fi).IsD() && (params.selectedOnly == false || fi->IsS())) + { + for(auto i=0; i<3; ++i) + { + PosType pi(&*fi, i); + ++candidates; + VertexPair bp = VertexPair(pi.V(), pi.VFlip()); + Point3 mp = (pi.V()->P()+pi.VFlip()->P())/2.f; + + if(testCollapse1(pi, mp, minQ, maxQ, params) && Collapser::LinkConditions(bp)) + { + //collapsing on pi.V() + bp = VertexPair(pi.VFlip(), pi.V()); + + Collapser::Do(m, bp, mp, true); + ++params.stat.collapseNum; + break; + } + + } + } + } + + ss.pop(); + } + + + //Here I just need to check the faces of the cross, since the other faces are not + //affected by the collapse of the internal faces of the cross. + static bool testCrossCollapse(PosType &p, std::vector ff, std::vector vi, Point3 &mp, Params ¶ms) + { + if(!checkFacesAfterCollapse(ff, p, mp, params, true)) + return false; + return true; + } + + /* + *Choose the best way to collapse a cross based on the (external) cross vertices valence + *and resulting face quality + * +0 -1 + * v1 v1 v1 + * /| \ /|\ / \ + * / | \ / | \ / \ + * / | \ / | \ / \ + * / *p| \ -1/ | \ -1 +0/ \+0 + * v0-------- v2 ========> v0 | v2 OR v0-------v2 + * \ | / \ | / \ / + * \ | / \ | / \ / + * \ | / \ | / \ / + * \ | / \|/ +0 \ / -1 + * v3 v3 v3 + */ + static bool chooseBestCrossCollapse(PosType &p, VertexPair& bp, vector &ff) + { + vector vv0, vv1, vv2, vv3; + VertexType *v0, *v1, *v2, *v3; + + v0 = p.F()->V1(p.VInd()); + v1 = p.F()->V2(p.VInd()); + + + bool crease[4] = {false, false, false, false}; + + crease[0] = p.F()->IsFaceEdgeS(VtoE(p.VInd(), (p.VInd()+1)%3)); + crease[1] = p.F()->IsFaceEdgeS(VtoE(p.VInd(), (p.VInd()+2)%3)); + + for(FaceType *f: ff) + if(!(*f).IsD() && f != p.F()) + { + PosType pi(f, p.V()); + VertexType *fv1 = pi.F()->V1(pi.VInd()); + VertexType *fv2 = pi.F()->V2(pi.VInd()); + + if(fv1 == v0 || fv2 == v0) + { + if (fv1 == 0) + { + v3 = fv2; + crease[3] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+2)%3)); + } + else + { + v3 = fv1; + crease[3] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+1)%3)); + } + // v3 = (fv1 == v0) ? fv2 : fv1; + } + + if(fv1 == v1 || fv2 == v1) + { + if (fv1 == v1) + { + v2 = fv2; + crease[2] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+2)%3)); + } + else + { + v2 = fv1; + crease[2] = f->IsFaceEdgeS(VtoE(pi.VInd(), (pi.VInd()+1)%3)); + } + // v2 = (fv1 == v1) ? fv2 : fv1; + } + } + + face::VVStarVF(v0, vv0); + face::VVStarVF(v1, vv1); + face::VVStarVF(v2, vv2); + face::VVStarVF(v3, vv3); + + int nv0 = vv0.size(), nv1 = vv1.size(); + int nv2 = vv2.size(), nv3 = vv3.size(); + + int delta1 = (idealValence(*v0) - nv0) + (idealValence(*v2) - nv2); + int delta2 = (idealValence(*v1) - nv1) + (idealValence(*v3) - nv3); + + ScalarType Q1 = std::min(Quality(v0->P(), v1->P(), v3->P()), Quality(v1->P(), v2->P(), v3->P())); + ScalarType Q2 = std::min(Quality(v0->P(), v1->P(), v2->P()), Quality(v2->P(), v3->P(), v0->P())); + + if (crease[0] || crease[1] || crease[2] || crease[3]) + return false; + // if (crease[0] && crease[1] && crease[2] && crease[3]) + // { + // return false; + // } + + // if (crease[0] || crease[2]) + // { + // bp = VertexPair(p.V(), v0); + // return true; + // } + + // if (crease[1] || crease[3]) + // { + // bp = VertexPair(p.V(), v1); + // return true; + // } + + //no crease + if(delta1 < delta2 && Q1 >= 0.6f*Q2) + { + bp = VertexPair(p.V(), v1); + return true; + } + else + { + bp = VertexPair(p.V(), v0); + return true; + } + } + //Cross Collapse pass: This pass cleans the mesh from cross vertices, keeping in mind the link conditions + //and feature preservations tests. + static void CollapseCrosses(MeshType &m , Params ¶ms) + { + tri::UpdateTopology::VertexFace(m); + tri::UpdateFlags::VertexBorderFromNone(m); + int count = 0; + + SelectionStack ss(m); + ss.push(); + + + { + tri::UpdateTopology::FaceFace(m); + Clean::CountNonManifoldVertexFF(m,true); + + //From now on Selection on vertices is not manifoldness + + for(auto fi=m.face.begin(); fi!=m.face.end(); ++fi) + if(!(*fi).IsD() && (!params.selectedOnly || fi->IsS())) + { + for(auto i=0; i<3; ++i) + { + PosType pi(&*fi, i); + if(!pi.V()->IsB()) + { + vector ff; + vector vi; + face::VFStarVF(pi.V(), ff, vi); + + //if cross need to check what creases you have and decide where to collapse accordingly + //if tricuspidis need whenever you have at least one crease => can't collapse anywhere + if(ff.size() == 4 || ff.size() == 3) + { + // VertexPair bp; + VertexPair bp = VertexPair(pi.V(), pi.VFlip()); + Point3 mp = (pi.V()->P()+pi.VFlip()->P())/2.f; + + if(testCollapse1(pi, mp, 0, 0, params, true) && Collapser::LinkConditions(bp)) + { + bp = VertexPair(pi.VFlip(), pi.V()); + Collapser::Do(m, bp, mp, true); + ++params.stat.collapseNum; + ++count; + break; + } + } + } + } + } + } + + ss.pop(); + Allocator::CompactEveryVector(m); + } + + // This function sets the selection bit on vertices that lie on creases + static int selectVertexFromCrease(MeshType &m, ScalarType creaseThr) + { + int count = 0; + Clean::CountNonManifoldVertexFF(m, true, false); + + ForEachFacePos(m, [&](PosType &p){ + if(p.IsBorder() || p.IsEdgeS()/*testCreaseEdge(p, creaseThr)*/) + { + p.V()->SetS(); + p.VFlip()->SetS(); + ++count; + } + }); + return count; + } + + static int selectVertexFromFold(MeshType &m, Params & params) + { + std::vector creaseVerts(m.VN(), 0); + ForEachFacePos(m, [&] (PosType & p) { + if (p.IsEdgeS()) + { + creaseVerts[vcg::tri::Index(m, p.V())] = 1; + creaseVerts[vcg::tri::Index(m, p.VFlip())] = 1; + } + }); + + + //this aspect ratio check doesn't work on cadish meshes (long thin triangles spanning whole mesh) +// ForEachFace(m, [&] (FaceType & f) { +// if (vcg::Quality(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr || vcg::DoubleArea(f) < 0.00001) +// { +// if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) +// f.V(0)->SetS(); +// if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) +// f.V(1)->SetS(); +// if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) +// f.V(2)->SetS(); +// } +// }); + + + ForEachFace(m, [&] (FaceType & f) { + for (int i = 0; i < 3; ++i) + { + if (f.FFp(i) > &f) + { + ScalarType angle = fastAngle(NormalizedTriangleNormal(f), NormalizedTriangleNormal(*(f.FFp(i)))); + if (angle <= params.foldAngleCosThr) + { + if (creaseVerts[vcg::tri::Index(m, f.V0(i))] == 0) + f.V0(i)->SetS(); + if (creaseVerts[vcg::tri::Index(m, f.V1(i))] == 0) + f.V1(i)->SetS(); + if (creaseVerts[vcg::tri::Index(m, f.V2(i))] == 0) + f.V2(i)->SetS(); + if (creaseVerts[vcg::tri::Index(m, f.FFp(i)->V2(f.FFi(i)))] == 0) + f.FFp(i)->V2(f.FFi(i))->SetS(); + } + } + } + }); + + return 0; + } + + + + + static void FoldRelax(MeshType &m, Params params, const int step, const bool strict = true) + { + typename vcg::tri::Smooth::LaplacianInfo lpz(CoordType(0, 0, 0), 0); + SimpleTempData::LaplacianInfo> TD(m.vert, lpz); + const ScalarType maxDist = (strict) ? params.maxSurfDist / 1000. : params.maxSurfDist; + for (int i = 0; i < step; ++i) + { + TD.Init(lpz); + vcg::tri::Smooth::AccumulateLaplacianInfo(m, TD, false); + + for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) + { + std::vector newPos(4); + bool moving = false; + + for (int j = 0; j < 3; ++j) + { + newPos[j] = fi->cP(j); + if (!fi->V(j)->IsD() && TD[fi->V(j)].cnt > 0) + { + if (fi->V(j)->IsS()) + { + newPos[j] = (fi->V(j)->P() + TD[fi->V(j)].sum) / (TD[fi->V(j)].cnt + 1); + moving = true; + } + } + } + + if (moving) + { + // const CoordType oldN = vcg::NormalizedTriangleNormal(*fi); + // const CoordType newN = vcg::Normal(newPos[0], newPos[1], newPos[2]).Normalize(); + + newPos[3] = (newPos[0] + newPos[1] + newPos[2]) / 3.; + if (/*(strict || oldN * newN > 0.99) &&*/ (!params.surfDistCheck || testHausdorff(*params.mProject, params.grid, newPos, maxDist))) + { + for (int j = 0; j < 3; ++j) + fi->V(j)->P() = newPos[j]; + } + } + } + } + } + + static void VertexCoordPlanarLaplacian(MeshType &m, Params & params, int step, ScalarType delta = 0.2) + { + typename vcg::tri::Smooth::LaplacianInfo lpz(CoordType(0, 0, 0), 0); + SimpleTempData::LaplacianInfo> TD(m.vert, lpz); + for (int i = 0; i < step; ++i) + { + TD.Init(lpz); + vcg::tri::Smooth::AccumulateLaplacianInfo(m, TD, false); + // First normalize the AccumulateLaplacianInfo + for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD() && TD[*vi].cnt > 0) + { + if ((*vi).IsS()) + TD[*vi].sum = ((*vi).P() + TD[*vi].sum) / (TD[*vi].cnt + 1); + } + + for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) + { + if (!(*fi).IsD()) + { + for (int j = 0; j < 3; ++j) + { + if (Angle(Normal(TD[(*fi).V0(j)].sum, (*fi).P1(j), (*fi).P2(j)), + Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) + TD[(*fi).V0(j)].sum = (*fi).P0(j); + } + } + } + for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) + { + if (!(*fi).IsD()) + { + for (int j = 0; j < 3; ++j) + { + if (Angle(Normal(TD[(*fi).V0(j)].sum, TD[(*fi).V1(j)].sum, (*fi).P2(j)), + Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) + { + TD[(*fi).V0(j)].sum = (*fi).P0(j); + TD[(*fi).V1(j)].sum = (*fi).P1(j); + } + } + } + } + + for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD() && TD[*vi].cnt > 0) + { + std::vector newPos(1, TD[*vi].sum); + if ((*vi).IsS() && testHausdorff(*params.mProject, params.grid, newPos, params.maxSurfDist)) + (*vi).P() = (*vi).P() * (1-delta) + TD[*vi].sum * (delta); + } + } // end step + } + + // static int + /** + * Simple Laplacian Smoothing step + * Border and crease vertices are kept fixed. + * If there are selected faces and the param.onlySelected is true we compute + * the set of internal vertices to the selection and we combine it in and with + * the vertexes not on border or creases + */ + static void ImproveByLaplacian(MeshType &m, Params params) + { + SelectionStack ss(m); + + if(params.selectedOnly) { + ss.push(); + tri::UpdateSelection::VertexFromFaceStrict(m); + ss.push(); + } + tri::UpdateTopology::FaceFace(m); + tri::UpdateFlags::VertexBorderFromFaceAdj(m); + tri::UpdateSelection::VertexFromBorderFlag(m); + selectVertexFromCrease(m, params.creaseAngleCosThr); + tri::UpdateSelection::VertexInvert(m); + if(params.selectedOnly) { + ss.popAnd(); + } + + VertexCoordPlanarLaplacian(m, params, 1); + + tri::UpdateSelection::VertexClear(m); + + selectVertexFromFold(m, params); + FoldRelax(m, params, 2); + + tri::UpdateSelection::VertexClear(m); + + if(params.selectedOnly) { + ss.pop(); + } + } + /* + Reprojection step, this method reprojects each vertex on the original surface + sampling the nearest Point3 onto it using a uniform grid StaticGrid t + */ + //TODO: improve crease reprojection: + // crease verts should reproject only on creases. + static void ProjectToSurface(MeshType &m, Params & params) + { + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) + if(!(*vi).IsD()) + { + Point3 newP, normP, barP; + ScalarType maxDist = params.maxSurfDist * 2.5f, minDist = 0.f; + FaceType* fp = GetClosestFaceBase(*params.mProject, params.grid, vi->cP(), maxDist, minDist, newP/*, normP, barP*/); + + if (fp != NULL) + { + vi->P() = newP; + } + } + } }; } // end namespace tri } // end namespace vcg From a65010f34d2498d82b1bc81669d2533c7f5e548d Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 12 Nov 2020 18:55:28 +0100 Subject: [PATCH 019/140] enable required VFAdjacency on tmp mesh on SplitManifoldComponents --- vcg/complex/algorithms/clean.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vcg/complex/algorithms/clean.h b/vcg/complex/algorithms/clean.h index eb77faf8..a52c8d75 100644 --- a/vcg/complex/algorithms/clean.h +++ b/vcg/complex/algorithms/clean.h @@ -685,6 +685,8 @@ public: UpdateFlags::FaceClearS(m); MeshType tmpMesh; + tmpMesh.vert.EnableVFAdjacency(); + tmpMesh.face.EnableVFAdjacency(); size_t selCnt=0; From 527953434d7d08cb07028f192be1db940dbe3896 Mon Sep 17 00:00:00 2001 From: korialis Date: Fri, 13 Nov 2020 15:30:38 +0100 Subject: [PATCH 020/140] bug fix on isotropic remeshing collapse strategy --- vcg/complex/algorithms/edge_collapse.h | 164 ++++++++++++------- vcg/complex/algorithms/isotropic_remeshing.h | 55 ++++--- 2 files changed, 132 insertions(+), 87 deletions(-) diff --git a/vcg/complex/algorithms/edge_collapse.h b/vcg/complex/algorithms/edge_collapse.h index 57da15b9..074edc6d 100644 --- a/vcg/complex/algorithms/edge_collapse.h +++ b/vcg/complex/algorithms/edge_collapse.h @@ -211,77 +211,117 @@ public: // To do a collapse onto a vertex simply pass p as the position of the surviving vertex static int Do(TriMeshType &m, VertexPair & c, const Point3 &p, const bool preserveFaceEdgeS = false) { - EdgeSet es; - FindSets(c,es); - - int n_face_del=0 ; + EdgeSet es, es1; + FindSets(c,es); - static int VtoE[3][3] = { -1, 0, 2, - 0, -1, 1, - 2, 1, -1 }; + if (preserveFaceEdgeS) + { + VertexPair c1(c.V(1), c.V(0)); + FindSets(c1, es1); + } -// bool toSel = false; + int n_face_del=0 ; - VertexType* top[2]; - std::map toSel; + static int VtoE[3][3] = { -1, 0, 2, + 0, -1, 1, + 2, 1, -1 }; - std::vector v2s; v2s.reserve(2); + std::vector topVertices; topVertices.reserve(2); + std::vector fan1V2S; fan1V2S.reserve(2); + std::vector v2s; v2s.reserve(2); + std::map toSel; - for(auto i=es.AV01().begin();i!=es.AV01().end();++i) - { - FaceType & f = *((*i).f); - assert(f.V((*i).z) == c.V(0)); - if (preserveFaceEdgeS && f.IsFaceEdgeS(VtoE[((*i).z+1)%3][((*i).z+2)%3])) - { -// std::cout << "2 " <::DeleteFace(m,f); - n_face_del++; - } - - // Very LOW LEVEL update of VF Adjacency; - // for all the faces incident in v[0] - // - v[0] will be deleted so we substitute v[0] with v[1] - // - we prepend that face to the list of the faces incident on v[1] - for(auto i=es.AV0().begin();i!=es.AV0().end();++i) - { - FaceType & f = *((*i).f); + if (preserveFaceEdgeS) + { + VertexPointer top; + size_t topIdx; + if (f.V(((*i).z+1)%3) == c.V(1)) + { + top = f.V(((*i).z+2)%3); + topIdx = ((*i).z+2)%3; + } + else + { + top = f.V(((*i).z+1)%3); + topIdx = ((*i).z+1)%3; + } - if (preserveFaceEdgeS) - { - for (size_t j = 0; j < v2s.size(); ++j) - { - if ((*i).f->V(((*i).z+1)%3) == v2s[j]) - { - (*i).f->SetFaceEdgeS(VtoE[((*i).z)%3][((*i).z+1)%3]); - break; - } - if ((*i).f->V(((*i).z+2)%3) == v2s[j]) - { - (*i).f->SetFaceEdgeS(VtoE[((*i).z)%3][((*i).z+2)%3]); - break; - } - } - } - (*i).f->V((*i).z) = c.V(1); // For each face in v0 we substitute v0 with v1 - (*i).f->VFp((*i).z) = c.V(1)->VFp(); - (*i).f->VFi((*i).z) = c.V(1)->VFi(); - c.V(1)->VFp() = (*i).f; - c.V(1)->VFi() = (*i).z; + topVertices.push_back(top); - } - - Allocator::DeleteVertex(m,*(c.V(0))); - c.V(1)->P()=p; - return n_face_del; + if (f.IsFaceEdgeS(VtoE[((*i).z)][topIdx])) + fan1V2S.push_back(top); + + if (f.IsFaceEdgeS(VtoE[((*i).z+1)%3][((*i).z+2)%3])) + v2s.push_back(top); + } + + vcg::face::VFDetach(f,((*i).z+1)%3); + vcg::face::VFDetach(f,((*i).z+2)%3); + Allocator::DeleteFace(m,f); + n_face_del++; + } + + // Very LOW LEVEL update of VF Adjacency; + // for all the faces incident in v[0] + // - v[0] will be deleted so we substitute v[0] with v[1] + // - we prepend that face to the list of the faces incident on v[1] + for(auto i=es.AV0().begin();i!=es.AV0().end();++i) + { + FaceType & f = *((*i).f); + + if (preserveFaceEdgeS) + { + for (size_t j = 0; j < v2s.size(); ++j) + { + if ((*i).f->V(((*i).z+1)%3) == v2s[j]) + { + (*i).f->SetFaceEdgeS(VtoE[((*i).z)%3][((*i).z+1)%3]); + break; + } + if ((*i).f->V(((*i).z+2)%3) == v2s[j]) + { + (*i).f->SetFaceEdgeS(VtoE[((*i).z)%3][((*i).z+2)%3]); + break; + } + } + } + (*i).f->V((*i).z) = c.V(1); // For each face in v0 we substitute v0 with v1 + (*i).f->VFp((*i).z) = c.V(1)->VFp(); + (*i).f->VFi((*i).z) = c.V(1)->VFi(); + c.V(1)->VFp() = (*i).f; + c.V(1)->VFi() = (*i).z; + } + + if (preserveFaceEdgeS) + { + for (auto i = es1.AV0().begin(); i != es1.AV0().end(); ++i) + { + FaceType & f = *((*i).f); + for (size_t j = 0; j < fan1V2S.size(); ++j) + { + if ((*i).f->V(((*i).z+1)%3) == fan1V2S[j]) + { + (*i).f->SetFaceEdgeS(VtoE[((*i).z)%3][((*i).z+1)%3]); + break; + } + if ((*i).f->V(((*i).z+2)%3) == fan1V2S[j]) + { + (*i).f->SetFaceEdgeS(VtoE[((*i).z)%3][((*i).z+2)%3]); + break; + } + } + } + } + + Allocator::DeleteVertex(m,*(c.V(0))); + c.V(1)->P()=p; + return n_face_del; } }; diff --git a/vcg/complex/algorithms/isotropic_remeshing.h b/vcg/complex/algorithms/isotropic_remeshing.h index 06ea33bb..f1f75e3a 100644 --- a/vcg/complex/algorithms/isotropic_remeshing.h +++ b/vcg/complex/algorithms/isotropic_remeshing.h @@ -407,7 +407,7 @@ private: FaceType* fp = GetClosestFaceBase(m, grid, v, maxD, dist, closest); //you can't use this kind of orientation check, since when you stand on edges it fails - if (fp == NULL /*|| (checkOrientation != CoordType(0,0,0) && checkOrientation * fp->N() < 0.5)*/) + if (fp == NULL || (checkOrientation != CoordType(0,0,0) && checkOrientation * fp->N() < 0.7)) { return false; } @@ -563,9 +563,9 @@ private: / \ /|\ / \ / | \ / \ / | \ - / _*p\ -1/ | \ -1 - v2--------v0 ========> v2 | v0 - \ / \ | / + / _*p\ -1/ | \ -1 + v2--------v0 ========> v2 | v0 + \ / \ | / \ / \ | / \ / \ | / \ / \|/ +1 @@ -761,18 +761,21 @@ private: int incidentFeatures = 0; + vcg::tri::UnMarkAll(*params.m); + for (size_t i = 0; i < faces.size(); ++i) - // if (faces[i] != p.F() && faces[i] != p.FFlip()) { - if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+1)%3))) + if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+1)%3)) && !vcg::tri::IsMarked(*params.m, faces[i]->cV1(vIdxes[i]))) { + vcg::tri::Mark(*params.m,faces[i]->cV1(vIdxes[i])); incidentFeatures++; CoordType movingEdgeVector0 = (faces[i]->cP1(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); if (std::fabs(movingEdgeVector0 * dEdgeVector) < .9f || !p.IsEdgeS()) return false; } - if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+2)%3))) + if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+2)%3)) && !vcg::tri::IsMarked(*params.m, faces[i]->cV2(vIdxes[i]))) { + vcg::tri::Mark(*params.m,faces[i]->cV2(vIdxes[i])); incidentFeatures++; CoordType movingEdgeVector1 = (faces[i]->cP2(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); if (std::fabs(movingEdgeVector1 * dEdgeVector) < .9f || !p.IsEdgeS()) @@ -781,7 +784,7 @@ private: allIncidentFaceSelected &= faces[i]->IsS(); } - if (incidentFeatures > 4) + if (incidentFeatures > 2) return false; return params.selectedOnly ? allIncidentFaceSelected : true; @@ -821,18 +824,23 @@ private: // float div = fastAngle(oldN, newN); // if(div < .9f ) return false; - if (oldN * newN < 0.8f) + if (oldN * newN < 0.5f) return false; // // check on new face distance from original mesh if (params.surfDistCheck) { - std::vector points(4); - points[0] = (v1->cP() + v2->cP() + mp) / 3.; - points[1] = (v1->cP() + mp) / 2.; - points[2] = (v2->cP() + mp) / 2.; - points[3] = mp; - if (!testHausdorff(*(params.mProject), params.grid, points, params.maxSurfDist, newN)) + std::vector points(3); + std::vector baryP(1); + + baryP[0] = (v1->cP() + v2->cP() + mp) / 3.; + + points[0] = (v1->cP() + mp) / 2.; + points[1] = (v2->cP() + mp) / 2.; + points[2] = mp; + + if (!testHausdorff(*(params.mProject), params.grid, points, params.maxSurfDist) || + !testHausdorff(*(params.mProject), params.grid, baryP, params.maxSurfDist, newN)) return false; } } @@ -842,7 +850,7 @@ private: //TODO: Refactor code and implement the correct set up of crease info when collapsing towards a crease edge - static bool checkCollapseFacesAroundVert1(PosType &p, Point3 &mp, Params ¶ms, bool relaxed) + static bool checkCollapseFacesAroundVert1(PosType &p, VertexPair & pair, Point3 &mp, Params ¶ms, bool relaxed) { PosType p0 = p, p1 = p; @@ -863,6 +871,8 @@ private: if (!moveable0 && !moveable1) return false; + pair = moveable0 ? VertexPair(p0.V(), p1.V()) : VertexPair(p1.V(), p0.V()); + //casting int(true) is always 1 and int(false) = =0 assert(int(true) == 1); assert(int(false) == 0); @@ -874,7 +884,7 @@ private: return false; } - static bool testCollapse1(PosType &p, Point3 &mp, ScalarType minQ, ScalarType maxQ, Params ¶ms, bool relaxed = false) + static bool testCollapse1(PosType &p, VertexPair & pair, Point3 &mp, ScalarType minQ, ScalarType maxQ, Params ¶ms, bool relaxed = false) { ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.5,(ScalarType)1.5, (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))) : (ScalarType)1; ScalarType dist = Distance(p.V()->P(), p.VFlip()->P()); @@ -882,7 +892,7 @@ private: ScalarType area = DoubleArea(*(p.F()))/2.f; if(relaxed || (dist < thr || area < params.minLength*params.minLength/100.f))//if to collapse { - return checkCollapseFacesAroundVert1(p, mp, params, relaxed); + return checkCollapseFacesAroundVert1(p, pair, mp, params, relaxed); } return false; } @@ -951,11 +961,8 @@ private: VertexPair bp = VertexPair(pi.V(), pi.VFlip()); Point3 mp = (pi.V()->P()+pi.VFlip()->P())/2.f; - if(testCollapse1(pi, mp, minQ, maxQ, params) && Collapser::LinkConditions(bp)) + if(testCollapse1(pi, bp, mp, minQ, maxQ, params) && Collapser::LinkConditions(bp)) { - //collapsing on pi.V() - bp = VertexPair(pi.VFlip(), pi.V()); - Collapser::Do(m, bp, mp, true); ++params.stat.collapseNum; break; @@ -964,7 +971,6 @@ private: } } } - ss.pop(); } @@ -1129,9 +1135,8 @@ private: VertexPair bp = VertexPair(pi.V(), pi.VFlip()); Point3 mp = (pi.V()->P()+pi.VFlip()->P())/2.f; - if(testCollapse1(pi, mp, 0, 0, params, true) && Collapser::LinkConditions(bp)) + if(testCollapse1(pi, bp, mp, 0, 0, params, true) && Collapser::LinkConditions(bp)) { - bp = VertexPair(pi.VFlip(), pi.V()); Collapser::Do(m, bp, mp, true); ++params.stat.collapseNum; ++count; From 6228d92fec3a460d17d6bc321e260bfd51b085a5 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Mon, 16 Nov 2020 09:54:18 +0100 Subject: [PATCH 021/140] solved crash for stl meshes > 2GB --- wrap/io_trimesh/import_stl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/io_trimesh/import_stl.h b/wrap/io_trimesh/import_stl.h index 90510e9d..11eb57c3 100644 --- a/wrap/io_trimesh/import_stl.h +++ b/wrap/io_trimesh/import_stl.h @@ -159,7 +159,7 @@ static bool IsSTLBinary(const char * filename, bool &binaryFlag) fseek(fp, STL_LABEL_SIZE, SEEK_SET); fread(&facenum, sizeof(unsigned int), 1, fp); - int expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; + long expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; if(file_size == expected_file_size) { binaryFlag = true; From c7fd93063ef2bc3b426148e2eb05ee9f50f4114b Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 17 Nov 2020 19:19:54 +0100 Subject: [PATCH 022/140] default copy constructor and assignment operator in Point2 and Point3 --- vcg/space/deprecated_point2.h | 14 ++++++++++---- vcg/space/deprecated_point3.h | 25 +++++++++++++++++++------ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/vcg/space/deprecated_point2.h b/vcg/space/deprecated_point2.h index 8085d6ed..6241e78d 100644 --- a/vcg/space/deprecated_point2.h +++ b/vcg/space/deprecated_point2.h @@ -127,14 +127,20 @@ public: _v[0] = nx; _v[1] = ny; } /// copy constructor - inline Point2 ( const Point2 & p) + inline Point2 ( const Point2 & p) = default; + /// copy constructor + template + inline Point2 ( const Point2 & p) { - _v[0]= p._v[0]; _v[1]= p._v[1]; + _v[0]= p[0]; _v[1]= p[1]; } /// copy - inline Point2 & operator =( const Point2 & p) + inline Point2 & operator =( const Point2 & p) = default; + /// copy + template + inline Point2 & operator =( const Point2 & p) { - _v[0]= p._v[0]; _v[1]= p._v[1]; + _v[0]= p[0]; _v[1]= p[1]; return *this; } /// sets the point to (0,0) diff --git a/vcg/space/deprecated_point3.h b/vcg/space/deprecated_point3.h index 1468e9bb..dd32ebfd 100644 --- a/vcg/space/deprecated_point3.h +++ b/vcg/space/deprecated_point3.h @@ -133,21 +133,34 @@ public: _v[1] = ny; _v[2] = nz; } - inline Point3 ( Point3 const & p ) + + /** Default copy constructor */ + inline Point3 ( Point3 const & p ) = default; + + /** Copy from Point with different template */ + template + inline Point3 ( Point3 const & p ) { - _v[0]= p._v[0]; - _v[1]= p._v[1]; - _v[2]= p._v[2]; + _v[0]= p[0]; + _v[1]= p[1]; + _v[2]= p[2]; } + inline Point3 ( const P3ScalarType nv[3] ) { _v[0] = nv[0]; _v[1] = nv[1]; _v[2] = nv[2]; } - inline Point3 & operator =(Point3 const & p) + + /** Default copy assignment */ + inline Point3 & operator =(Point3 const & p) = default; + + /** Copy assignment from Point with different template */ + template + inline Point3 & operator =(Point3 const & p) { - _v[0] = p._v[0]; _v[1] = p._v[1]; _v[2] = p._v[2]; + _v[0] = p[0]; _v[1] = p[1]; _v[2] = p[2]; return *this; } inline void SetZero() From 59548afa487165d730a17eb5f75426e0bb83952a Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 19 Nov 2020 17:40:32 +0100 Subject: [PATCH 023/140] import ply supports uint type for edge properties vertex1 and vertex2 --- wrap/io_trimesh/import_ply.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/wrap/io_trimesh/import_ply.h b/wrap/io_trimesh/import_ply.h index f8d955c4..d94dc5fa 100644 --- a/wrap/io_trimesh/import_ply.h +++ b/wrap/io_trimesh/import_ply.h @@ -254,10 +254,12 @@ public: static const PropDescriptor &EdgeDesc(int i) { - static const PropDescriptor qf[2]= + static const PropDescriptor qf[4]= { - {"edge","vertex1", ply::T_INT, ply::T_INT, offsetof(LoadPly_EdgeAux,v1), 0,0,0,0,0 ,0}, - {"edge","vertex2", ply::T_INT, ply::T_INT, offsetof(LoadPly_EdgeAux,v2), 0,0,0,0,0 ,0}, + {"edge","vertex1", ply::T_INT, ply::T_INT, offsetof(LoadPly_EdgeAux,v1), 0,0,0,0,0 ,0}, + {"edge","vertex2", ply::T_INT, ply::T_INT, offsetof(LoadPly_EdgeAux,v2), 0,0,0,0,0 ,0}, + {"edge","vertex1", ply::T_UINT, ply::T_INT, offsetof(LoadPly_EdgeAux,v1), 0,0,0,0,0 ,0}, + {"edge","vertex2", ply::T_UINT, ply::T_INT, offsetof(LoadPly_EdgeAux,v2), 0,0,0,0,0 ,0}, }; return qf[i]; } @@ -452,7 +454,8 @@ public: } // Optional flag descriptors - if(pf.AddToRead(EdgeDesc(0) )!= -1 && pf.AddToRead(EdgeDesc(1)) != -1 ) + if((pf.AddToRead(EdgeDesc(0) )!= -1 || pf.AddToRead(EdgeDesc(2) )!= -1) && + (pf.AddToRead(EdgeDesc(1)) != -1 || pf.AddToRead(EdgeDesc(3)) != -1)) pi.mask |= Mask::IOM_EDGEINDEX; if(vcg::tri::HasPerVertexFlags(m) && pf.AddToRead(VertDesc(3))!=-1 ) From d2b39eb0bb1c14f28eb57e14c142450e232191a1 Mon Sep 17 00:00:00 2001 From: nico Date: Sun, 22 Nov 2020 09:46:04 +1000 Subject: [PATCH 024/140] Added a signed measure of distortion to see Compresssion/Stretch --- .../algorithms/parametrization/distortion.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/vcg/complex/algorithms/parametrization/distortion.h b/vcg/complex/algorithms/parametrization/distortion.h index 903d8553..9ef99b5a 100644 --- a/vcg/complex/algorithms/parametrization/distortion.h +++ b/vcg/complex/algorithms/parametrization/distortion.h @@ -185,7 +185,7 @@ public: public: - enum DistType{AreaDist,EdgeDist,AngleDist,CrossDist,L2Stretch,LInfStretch,ARAPDist}; + enum DistType{AreaDist,EdgeDist,EdgeComprStretch,AngleDist,CrossDist,L2Stretch,LInfStretch,ARAPDist}; ///return the absolute difference between angle in 3D space and texture space ///Actually the difference in cos space @@ -242,12 +242,19 @@ public: ///the needed scaling factor EdgeScaleVal may be calculated ///by using the ScalingFactor function static ScalarType EdgeDistortion(const FaceType *f,int e, - ScalarType EdgeScaleVal) + ScalarType EdgeScaleVal, + bool AbsValue=true) { ScalarType edgeUV=EdgeLenghtUV(f,e)*EdgeScaleVal; ScalarType edge3D=EdgeLenght3D(f,e); assert(edge3D > 0); - ScalarType diff=fabs(edge3D-edgeUV)/edge3D; + + ScalarType diff=0; + if (AbsValue) + diff=fabs(edge3D-edgeUV)/edge3D; + else + diff=(edge3D-edgeUV)/edge3D; + assert(!math::IsNAN(diff)); return diff; } @@ -505,6 +512,11 @@ public: EdgeDistortion(&m.face[i],1,edge_scale)+ EdgeDistortion(&m.face[i],2,edge_scale) )/3; break; + case EdgeComprStretch: + q =( EdgeDistortion(&m.face[i],0,edge_scale,false)+ + EdgeDistortion(&m.face[i],1,edge_scale,false)+ + EdgeDistortion(&m.face[i],2,edge_scale,false) )/3; + break; case L2Stretch: q = L2StretchEnergySquared( &m.face[i],area_scale ); break; From 19a7d7c67257dcd7e5e2276c2da3014bbceb637c Mon Sep 17 00:00:00 2001 From: nico Date: Sun, 22 Nov 2020 09:46:48 +1000 Subject: [PATCH 025/140] Added the possibility to add some small border on each packed rectangle in PackAsObjectOrientedRect --- vcg/space/outline2_packer.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vcg/space/outline2_packer.h b/vcg/space/outline2_packer.h index ff01bb0b..5343ad0b 100644 --- a/vcg/space/outline2_packer.h +++ b/vcg/space/outline2_packer.h @@ -143,7 +143,8 @@ static bool PackAsAxisAlignedRect(const std::vector< std::vector > &pol static bool PackAsObjectOrientedRect(const std::vector< std::vector > &polyVec, const Point2i containerSizeX, std::vector &trVec, - Point2x &coveredContainer) + Point2x &coveredContainer, + SCALAR_TYPE border=0) { trVec.clear(); trVec.resize(polyVec.size()); @@ -153,6 +154,8 @@ static bool PackAsObjectOrientedRect(const std::vector< std::vector > & { float rot; bbVec.push_back(getPolyOOBB(polyVec[i],rot)); + if (border>0) + bbVec.back().Offset(border); rotVec.push_back(rot); } From 6d2f4225dd8b2f9149431a01fc5d6aff74eb189d Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Mon, 23 Nov 2020 16:49:40 +0100 Subject: [PATCH 026/140] added ToEigenVector functions to Point4 --- vcg/space/deprecated_point4.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/vcg/space/deprecated_point4.h b/vcg/space/deprecated_point4.h index a27d9263..a932f43d 100644 --- a/vcg/space/deprecated_point4.h +++ b/vcg/space/deprecated_point4.h @@ -121,6 +121,22 @@ public: _v[2] = T(b[2]); _v[3] = T(b[3]); } + template + inline void ToEigenVector( EigenVector & b ) const + { + b[0]=_v[0]; + b[1]=_v[1]; + b[2]=_v[2]; + b[3]=_v[3]; + } + template + inline EigenVector ToEigenVector(void) const + { + assert(EigenVector::RowsAtCompileTime == 4); + EigenVector b; + b << _v[0], _v[1], _v[2], _v[3]; + return b; + } /// constructor that imports from different Point4 types template static inline Point4 Construct( const Point4 & b ) From 0ebdeb2bc9794b3690260a599aeb40db5ad9d826 Mon Sep 17 00:00:00 2001 From: nico Date: Tue, 24 Nov 2020 17:16:17 +1000 Subject: [PATCH 027/140] added border singularity check --- .../parametrization/tangent_field_operators.h | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/vcg/complex/algorithms/parametrization/tangent_field_operators.h b/vcg/complex/algorithms/parametrization/tangent_field_operators.h index 85b5a029..5dd485b1 100644 --- a/vcg/complex/algorithms/parametrization/tangent_field_operators.h +++ b/vcg/complex/algorithms/parametrization/tangent_field_operators.h @@ -821,7 +821,12 @@ public: { ///first it rotate dir to match with f1 CoordType dirS=CrossVector(f0,dir0); - CoordType dirR=vcg::tri::CrossField::Rotate(f0,f1,dirS); + ScalarType DotN=(f0.cN()*f1.cN()); + CoordType dirR; + if (DotN<(-0.99999)) + dirR=-dirS; + else + dirR=vcg::tri::CrossField::Rotate(f0,f1,dirS); ///then get the closest upf to K*PI/2 rotations //CoordType dir1=f1.cPD1(); //int ret=I_K_PI(dir1,dirR,f1.cN()); @@ -838,7 +843,6 @@ public: ret=i; } } - assert(ret!=-1); return ret; @@ -1347,13 +1351,14 @@ public: } + ///return true if a given vertex is singular, ///return also the missmatch - static bool IsSingularByCross(const VertexType &v,int &missmatch) + static bool IsSingularByCross(const VertexType &v,int &missmatch,bool BorderSing=false) { typedef typename VertexType::FaceType FaceType; ///check that is on border.. - if (v.IsB())return false; + if (v.IsB()&& (!BorderSing))return false; std::vector > posVec; //SortedFaces(v,faces); @@ -1374,7 +1379,7 @@ public: } ///select singular vertices - static void UpdateSingularByCross(MeshType &mesh) + static void UpdateSingularByCross(MeshType &mesh,bool addBorderSing=false) { bool hasSingular = vcg::tri::HasPerVertexAttribute(mesh,std::string("Singular")); bool hasSingularIndex = vcg::tri::HasPerVertexAttribute(mesh,std::string("SingularIndex")); @@ -1395,16 +1400,8 @@ public: for (size_t i=0;i Date: Tue, 24 Nov 2020 17:17:10 +1000 Subject: [PATCH 028/140] reversed the order of VFOrderedStar when it has found a border.. in order to be coherent with the others --- vcg/simplex/face/topology.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vcg/simplex/face/topology.h b/vcg/simplex/face/topology.h index d17ca0f6..7e84315d 100644 --- a/vcg/simplex/face/topology.h +++ b/vcg/simplex/face/topology.h @@ -1175,6 +1175,8 @@ void VFOrderedStarFF(const Pos &startPos, assert((posVec.size()%2)==0); posVec.erase(posVec.begin()+firstBorderInd+1+halfSize, posVec.end()); posVec.erase(posVec.begin(),posVec.begin()+firstBorderInd+1); + //reverse because canceled on ccw dir + std::reverse(posVec.begin(), posVec.end()); assert(posVec.size()==halfSize); } } From b6bdb06b5f4eed050be97c35224846c2f05aea44 Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 25 Nov 2020 17:50:22 +1000 Subject: [PATCH 029/140] exposed the type of matrix as public --- vcg/complex/algorithms/mesh_to_matrix.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/mesh_to_matrix.h b/vcg/complex/algorithms/mesh_to_matrix.h index dc22ffb9..c85edf8b 100644 --- a/vcg/complex/algorithms/mesh_to_matrix.h +++ b/vcg/complex/algorithms/mesh_to_matrix.h @@ -42,8 +42,9 @@ class MeshToMatrix typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::ScalarType ScalarType; +public: typedef typename Eigen::Matrix MatrixXm; - +private: static void GetTriEdgeAdjacency(const MatrixXm& V, const Eigen::MatrixXi& F, Eigen::MatrixXi& EV, From 9b6f9df6cc251d352e76f9d5a46612d11b4f78c8 Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 25 Nov 2020 17:51:02 +1000 Subject: [PATCH 030/140] added the possibility to work on any kind of scalar for mesh --- wrap/igl/smooth_field.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/wrap/igl/smooth_field.h b/wrap/igl/smooth_field.h index 8c17e4a1..6a3a6674 100644 --- a/wrap/igl/smooth_field.h +++ b/wrap/igl/smooth_field.h @@ -235,9 +235,10 @@ class FieldSmoother #ifdef COMISO_FIELD assert((Ndir==2)||(Ndir==4)); Eigen::MatrixXi F; - Eigen::MatrixXd V; + typename vcg::tri::MeshToMatrix::MatrixXm Vf; - MeshToMatrix::GetTriMeshData(mesh,F,V); + MeshToMatrix::GetTriMeshData(mesh,F,Vf); + Eigen::MatrixXd V = Vf.template cast(); Eigen::MatrixXd output_field; Eigen::VectorXd output_sing; @@ -275,12 +276,14 @@ class FieldSmoother assert((Ndir==2)||(Ndir==4)); Eigen::MatrixXi F; - Eigen::MatrixXd V; - - MeshToMatrix::GetTriMeshData(mesh,F,V); + typename vcg::tri::MeshToMatrix::MatrixXm Vf; + //Eigen::MatrixXd V; + MeshToMatrix::GetTriMeshData(mesh,F,Vf); + //then cast + Eigen::MatrixXd V = Vf.template cast(); Eigen::MatrixXd output_field; - Eigen::VectorXd output_sing; + //Eigen::VectorXd output_sing; igl::n_polyvector(V,F,HardI,HardD,output_field); @@ -402,10 +405,11 @@ public: tri::RequirePerVertexCurvatureDir(mesh); Eigen::MatrixXi F; - Eigen::MatrixXd V; + typename vcg::tri::MeshToMatrix::MatrixXm Vf; Eigen::MatrixXd PD1,PD2,PV1,PV2; - MeshToMatrix::GetTriMeshData(mesh,F,V); + MeshToMatrix::GetTriMeshData(mesh,F,Vf); + Eigen::MatrixXd V = Vf.template cast(); igl::principal_curvature(V,F,PD1,PD2,PV1,PV2,Nring,true); From 141a27104e5838aa1534b1c4bb213143f0c3d42c Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Wed, 25 Nov 2020 09:59:29 +0100 Subject: [PATCH 031/140] fixed nanoply warnings --- vcg/space/deprecated_point.h | 8 ++++---- wrap/nanoply/include/nanoply.hpp | 8 ++++++-- wrap/nanoply/include/nanoplyWrapper.hpp | 8 ++++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/vcg/space/deprecated_point.h b/vcg/space/deprecated_point.h index c973fa81..9c4dde92 100644 --- a/vcg/space/deprecated_point.h +++ b/vcg/space/deprecated_point.h @@ -164,14 +164,14 @@ public: } inline const S &X() const { return _v[0]; } inline const S &Y() const { return _v[1]; } - inline const S &Z() const { static_assert(N>2); return _v[2]; } + inline const S &Z() const { static_assert(N>2, "wrong point dimension"); return _v[2]; } /// W is in any case the last coordinate. /// (in a 2D point, W() == Y(). In a 3D point, W()==Z() /// in a 4D point, W() is a separate component) inline const S &W() const { return _v[N-1]; } inline S &X() { return _v[0]; } inline S &Y() { return _v[1]; } - inline S &Z() { static_assert(N>2); return _v[2]; } + inline S &Z() { static_assert(N>2, "wrong point dimension"); return _v[2]; } inline S &W() { return _v[N-1]; } inline const S * V() const { @@ -359,7 +359,7 @@ public: (provided for uniformity with other spatial classes. trivial for points) **/ - inline PointType LocalToGlobal(ParamType p) const{ + inline PointType LocalToGlobal(ParamType /*p*/) const{ return *this; } inline ParamType GlobalToLocal(PointType /*p*/) const{ @@ -798,7 +798,7 @@ public: PointType n = Norm(); if(n!=0.0) { n=1.0/n; _v[0]*=n; _v[1]*=n; _v[2]*=n; _v[3]*=n; } return *this;}; - template PointType & Normalize(const PT &p){ + template PointType & Normalize(const PT &/*p*/){ PointType n = Norm(); if(n!=0.0) { n=1.0/n; V(0)*=n; V(1)*=n; V(2)*=n; V(3)*=n; } return *this;}; diff --git a/wrap/nanoply/include/nanoply.hpp b/wrap/nanoply/include/nanoply.hpp index 2205bf2a..10415db5 100644 --- a/wrap/nanoply/include/nanoply.hpp +++ b/wrap/nanoply/include/nanoply.hpp @@ -2728,12 +2728,16 @@ namespace nanoply } template < typename TupleType, size_t ActionType> - inline bool TupleForEach(TupleType &tuple, PlyElement &elem, PlyFile& file, bool fixEndian, SizeT<0> t, SizeT a) { return false; } + inline bool TupleForEach(TupleType &tuple, PlyElement &elem, PlyFile& file, bool fixEndian, SizeT<0> t, SizeT a) + { + (void)tuple; (void)elem; (void)file; (void)fixEndian; (void)t; (void)a; + return false; + } template < typename TupleType, size_t N, size_t ActionType> inline bool TupleForEach(TupleType &tuple, PlyElement &elem, PlyFile& file, bool fixEndian, SizeT t, SizeT a) { - (void)t; + (void)t; typename std::tuple_element::type &elemDescr = std::get(tuple); if ((elemDescr.elem != PlyElemEntity::NNP_UNKNOWN_ELEM && elemDescr.elem == elem.plyElem) || (elemDescr.elem == PlyElemEntity::NNP_UNKNOWN_ELEM && elemDescr.name == elem.name)) diff --git a/wrap/nanoply/include/nanoplyWrapper.hpp b/wrap/nanoply/include/nanoplyWrapper.hpp index ebef9398..abab3417 100644 --- a/wrap/nanoply/include/nanoplyWrapper.hpp +++ b/wrap/nanoply/include/nanoplyWrapper.hpp @@ -553,7 +553,7 @@ namespace nanoply else tempProp[i] = p; } - unsigned int r = (bitType & (~tempProp[0].type)); + unsigned int r = (bitType & (~tempProp[0].type)); (void)r; if (tempProp.size() > 1 && ((bitType & (~tempProp[0].type)) == 0)) { if (tempProp.size() == 2) @@ -670,6 +670,7 @@ namespace nanoply template >::value> static unsigned int EnableVertexOcf(typename T::VertContainer& cont, unsigned int mask) { + (void)cont; (void)mask; return 0; } @@ -718,6 +719,7 @@ namespace nanoply template >::value> static unsigned int EnableFaceOcf(typename T::FaceContainer& cont, unsigned int mask) { + (void)cont; (void)mask; return 0; } @@ -773,6 +775,7 @@ namespace nanoply template >::value> static unsigned int VertexOcfMask(typename T::VertContainer& cont) { + (void)cont; return 0; } @@ -800,6 +803,7 @@ namespace nanoply template >::value> static unsigned int FaceOcfMask(typename T::FaceContainer& cont) { + (void)cont; return 0; } @@ -1590,7 +1594,7 @@ namespace nanoply if (!userDescr) custom.CreateFaceAttribDescriptor(&(*ai)); } - for (int i = 0; i < custom.faceAttrib.size(); i++) + for (size_t i = 0; i < custom.faceAttrib.size(); i++) { faceProp.push_back(custom.faceAttribProp[i]); faceDescr.dataDescriptor.push_back(custom.faceAttrib[i]); From c0e4cc9fc8156a56293988654ed9ddddd00a8024 Mon Sep 17 00:00:00 2001 From: korialis Date: Fri, 27 Nov 2020 10:44:04 +0100 Subject: [PATCH 032/140] minor changes to isotropic + update to adaptive strategy --- vcg/complex/algorithms/isotropic_remeshing.h | 113 ++++++++++++++----- 1 file changed, 86 insertions(+), 27 deletions(-) diff --git a/vcg/complex/algorithms/isotropic_remeshing.h b/vcg/complex/algorithms/isotropic_remeshing.h index f1f75e3a..acea7280 100644 --- a/vcg/complex/algorithms/isotropic_remeshing.h +++ b/vcg/complex/algorithms/isotropic_remeshing.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -194,7 +195,7 @@ private: auto areaRatio = vcg::DoubleArea(biggestSmallest.first) / vcg::DoubleArea(biggestSmallest.second); bool normalCheck = true; -// if (n1.Norm() > 0.001 && n2.Norm() > 0.001) + // if (n1.Norm() > 0.001 && n2.Norm() > 0.001) { auto referenceNormal = vcg::NormalizedTriangleNormal(biggestSmallest.first); @@ -276,16 +277,18 @@ public: tri::UpdateFlags::VertexBorderFromFaceAdj(toRemesh); tri::UpdateTopology::VertexFace(toRemesh); - // computeQuality(toRemesh); - // tri::UpdateQuality::VertexSaturate(toRemesh); - tagCreaseEdges(toRemesh, params); for(int i=0; i < params.iter; ++i) { - // params.stat.Reset(); if(cb) cb(100*i/params.iter, "Remeshing"); + if (params.adapt) + { + computeQualityDistFromCrease(toRemesh); + tri::Smooth::VertexQualityLaplacian(toRemesh, 2); + } + if(params.splitFlag) SplitLongEdges(toRemesh, params); #ifdef DEBUG_CREASE @@ -354,7 +357,7 @@ private: if(!(*vi).IsD()) { vector ff; - face::VFExtendedStarVF(&*vi, 0, ff); + face::VFExtendedStarVF(&*vi, 2, ff); ScalarType tot = 0.f; auto it = ff.begin(); @@ -368,6 +371,35 @@ private: vi->Q() = tot / (ScalarType)(std::max(1, ((int)ff.size()-1))); vi->SetV(); } + tri::Smooth::VertexQualityLaplacian(m, 3); + } + + static void computeQualityDistFromCrease(MeshType & m) + { + tri::RequirePerVertexQuality(m); + tri::UpdateTopology::FaceFace(m); +// tri::UpdateFlags::VertexClearV(m); + + std::vector seeds; + ForEachFace(m, [&] (FaceType & f) { + for (int i = 0; i < 3; ++i) + { + if (f.IsFaceEdgeS(i)) + { + seeds.push_back(f.V0(i)); + seeds.push_back(f.V1(i)); + } + } + }); + + tri::EuclideanDistance eu; + tri::Geodesic::PerVertexDijkstraCompute(m, seeds, eu); + tri::Smooth::VertexQualityLaplacian(m, 2); + + ForEachVertex(m, [] (VertexType & v) { + v.Q() = 1 / (v.Q() + 1); + }); + } /* @@ -422,6 +454,7 @@ private: vcg::tri::UpdateFlags::VertexClearV(m); std::queue creaseQueue; + ForEachFacePos(m, [&](PosType &p){ if (p.IsBorder()) @@ -441,11 +474,30 @@ private: if (!params.userSelectedCreases && (testCreaseEdge(p, params.creaseAngleCosThr) /*&& areaCheck*//* && qualityCheck*/) || p.IsBorder()) { PosType pp = p; + std::vector faces; + std::vector edges; + bool allOk = true; + do { - pp.F()->SetFaceEdgeS(pp.E()); + faces.push_back(pp.F()); + edges.push_back(pp.E()); + // pp.F()->SetFaceEdgeS(pp.E()); + if (vcg::QualityRadii(pp.F()->cP(0), pp.F()->cP(1), pp.F()->cP(2)) <= 0.0001) + { + allOk = false; + break; + } pp.NextF(); } while (pp != p); + if (allOk) + { + for (int i = 0; i < faces.size(); ++i) + { + faces[i]->SetFaceEdgeS(edges[i]); + } + } + creaseQueue.push(p); } } @@ -687,9 +739,9 @@ private: ScalarType length, lengthThr, minQ, maxQ; bool operator()(PosType &ep) { - ScalarType mult = math::ClampedLerp((ScalarType)0.5,(ScalarType)1.5, (((math::Abs(ep.V()->Q())+math::Abs(ep.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))); + ScalarType mult = math::ClampedLerp((ScalarType)0.25,(ScalarType)4, (((math::Abs(ep.V()->Q())+math::Abs(ep.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))); ScalarType dist = Distance(ep.V()->P(), ep.VFlip()->P()); - if(dist > std::max(mult*length,lengthThr*2)) + if(dist > mult * length) { ++count; return true; @@ -731,7 +783,7 @@ private: ep.maxQ = maxQ; ep.length = params.maxLength; ep.lengthThr = params.lengthThr; - tri::RefineE(m,midFunctor,ep); + tri::RefineMidpoint(m,ep, params.selectedOnly); params.stat.splitNum+=ep.count; } else { @@ -822,12 +874,19 @@ private: Point3 oldN = NormalizedTriangleNormal(*(pi.F())); Point3 newN = Normal(mp, v1->P(), v2->P()).Normalize(); -// float div = fastAngle(oldN, newN); -// if(div < .9f ) return false; + // float div = fastAngle(oldN, newN); + // if(div < .9f ) return false; if (oldN * newN < 0.5f) return false; - // // check on new face distance from original mesh + + std::vector baryP(1); + baryP[0] = (v1->cP() + v2->cP() + mp) / 3.; + + if (!testHausdorff(*(params.mProject), params.grid, baryP, params.maxSurfDist, newN)) + return false; + + //check on new face distance from original mesh if (params.surfDistCheck) { std::vector points(3); @@ -839,8 +898,8 @@ private: points[1] = (v2->cP() + mp) / 2.; points[2] = mp; - if (!testHausdorff(*(params.mProject), params.grid, points, params.maxSurfDist) || - !testHausdorff(*(params.mProject), params.grid, baryP, params.maxSurfDist, newN)) + if (!testHausdorff(*(params.mProject), params.grid, points, params.maxSurfDist))// || +// !testHausdorff(*(params.mProject), params.grid, baryP, params.maxSurfDist, newN)) return false; } } @@ -886,7 +945,7 @@ private: static bool testCollapse1(PosType &p, VertexPair & pair, Point3 &mp, ScalarType minQ, ScalarType maxQ, Params ¶ms, bool relaxed = false) { - ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.5,(ScalarType)1.5, (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))) : (ScalarType)1; + ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.25,(ScalarType)4, (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))) : (ScalarType)1; ScalarType dist = Distance(p.V()->P(), p.VFlip()->P()); ScalarType thr = mult*params.minLength; ScalarType area = DoubleArea(*(p.F()))/2.f; @@ -1182,17 +1241,17 @@ private: //this aspect ratio check doesn't work on cadish meshes (long thin triangles spanning whole mesh) -// ForEachFace(m, [&] (FaceType & f) { -// if (vcg::Quality(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr || vcg::DoubleArea(f) < 0.00001) -// { -// if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) -// f.V(0)->SetS(); -// if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) -// f.V(1)->SetS(); -// if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) -// f.V(2)->SetS(); -// } -// }); + // ForEachFace(m, [&] (FaceType & f) { + // if (vcg::Quality(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr || vcg::DoubleArea(f) < 0.00001) + // { + // if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) + // f.V(0)->SetS(); + // if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) + // f.V(1)->SetS(); + // if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) + // f.V(2)->SetS(); + // } + // }); ForEachFace(m, [&] (FaceType & f) { From cc0bd7b1e267e884c73f680cfadedfa96de6aacc Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Mon, 30 Nov 2020 10:59:15 +0100 Subject: [PATCH 033/140] fix exif include --- wrap/io_trimesh/import_out.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/io_trimesh/import_out.h b/wrap/io_trimesh/import_out.h index 0564dbcc..cbf438c1 100644 --- a/wrap/io_trimesh/import_out.h +++ b/wrap/io_trimesh/import_out.h @@ -32,7 +32,7 @@ #include #include #include -#include //external easyexif lib +#include "exif.h" //external easyexif lib namespace vcg { namespace tri { From a1774eb7b5ca85a4d7054abd5ad51b864900cfc9 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Mon, 30 Nov 2020 14:41:08 +0100 Subject: [PATCH 034/140] added rule about pull requests --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f9065e7e..3d7cc66e 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,15 @@ A number of applications have been developed using the vcglib: - Metro, the tool for measuring differences between meshes - The first high quality out-of-core mesh simplifier that was used by the Stanford Digital Michelangelo project to process their huge 3D scanned models. +## Contributing +In case of bugs please report them [here](https://github.com/cnr-isti-vclab/vcglib/issues). +Copyright of the library is fully owned by CNR. Contributing means signing an appropriate license agreement. +Pull request about trivial, small, questionable updates (e.g. small stylistic changes will int -> uint8_t) will be rejected without discussion. + + ## Contacts For any info about licensing (portion of) the library please contact us: Paolo Cignoni (p.cignoni@isti.cnr.it) Visual Computing Lab of the Italian National Research Council - ISTI -In case of bugs please report them [here](https://github.com/cnr-isti-vclab/vcglib/issues) . From 94d1f8d9fc7540dc85b3a8a67a2f1fc0abb5020e Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Mon, 30 Nov 2020 14:43:10 +0100 Subject: [PATCH 035/140] typo in readme.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3d7cc66e..63209851 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,10 @@ A number of applications have been developed using the vcglib: ## Contributing In case of bugs please report them [here](https://github.com/cnr-isti-vclab/vcglib/issues). -Copyright of the library is fully owned by CNR. Contributing means signing an appropriate license agreement. -Pull request about trivial, small, questionable updates (e.g. small stylistic changes will int -> uint8_t) will be rejected without discussion. + +Copyright of the library is fully owned by CNR. Contributing means signing an appropriate [license agreement](https://github.com/cnr-isti-vclab/vcglib/blob/master/docs/ContributorLicenseAgreement.pdf) . + +Pull requests about trivial, small, questionable updates (e.g. small stylistic changes like int -> uint8_t) will be rejected without discussion. ## Contacts From 1368813fb4a84bcc04620d91aef525a8a4e54291 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 1 Dec 2020 11:59:49 +0100 Subject: [PATCH 036/140] fix deprecated add-path on github actions windows workflow --- .github/workflows/BuildSamplesWindows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/BuildSamplesWindows.yml b/.github/workflows/BuildSamplesWindows.yml index 999008ea..0b4ca556 100644 --- a/.github/workflows/BuildSamplesWindows.yml +++ b/.github/workflows/BuildSamplesWindows.yml @@ -9,12 +9,12 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Downlaod Jom + - name: Download Jom run: | Invoke-WebRequest -Uri "http://download.qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" New-Item -Name "jom" -ItemType "directory" Expand-Archive -Path jom_1_1_3.zip -DestinationPath .\jom - echo "::add-path::$(Get-Location)\jom" + echo "$(Get-Location)\jom" >> GITHUB_PATH - name: Setup env variables id: envs run: | From 52a469631b9599ccd2b1c7c6c1d22d5bcc998f39 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 1 Dec 2020 12:02:18 +0100 Subject: [PATCH 037/140] fix deprecated set-env on github actions windows workflow --- .github/workflows/BuildSamplesWindows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/BuildSamplesWindows.yml b/.github/workflows/BuildSamplesWindows.yml index 0b4ca556..ef74176e 100644 --- a/.github/workflows/BuildSamplesWindows.yml +++ b/.github/workflows/BuildSamplesWindows.yml @@ -18,7 +18,7 @@ jobs: - name: Setup env variables id: envs run: | - echo '::set-env name=VCINSTALLDIR::C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC' + echo "VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC" >> $GITHUB_ENV - name: Setup MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Install Qt From 99d12d7d1fa2f52823af5e92660cb13998c9d6bc Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 1 Dec 2020 12:11:49 +0100 Subject: [PATCH 038/140] windows workflow fix to ps script --- .github/workflows/BuildSamplesWindows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/BuildSamplesWindows.yml b/.github/workflows/BuildSamplesWindows.yml index ef74176e..fe07665d 100644 --- a/.github/workflows/BuildSamplesWindows.yml +++ b/.github/workflows/BuildSamplesWindows.yml @@ -14,7 +14,7 @@ jobs: Invoke-WebRequest -Uri "http://download.qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" New-Item -Name "jom" -ItemType "directory" Expand-Archive -Path jom_1_1_3.zip -DestinationPath .\jom - echo "$(Get-Location)\jom" >> GITHUB_PATH + echo "$(Get-Location)\jom" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Setup env variables id: envs run: | From 76442ee55f901e91449e558e2a659a070f9b4645 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Wed, 2 Dec 2020 21:33:00 +0100 Subject: [PATCH 039/140] reverted the function VFOrderedStarFF as it needs further investigation --- vcg/simplex/face/topology.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/vcg/simplex/face/topology.h b/vcg/simplex/face/topology.h index 7e84315d..d17ca0f6 100644 --- a/vcg/simplex/face/topology.h +++ b/vcg/simplex/face/topology.h @@ -1175,8 +1175,6 @@ void VFOrderedStarFF(const Pos &startPos, assert((posVec.size()%2)==0); posVec.erase(posVec.begin()+firstBorderInd+1+halfSize, posVec.end()); posVec.erase(posVec.begin(),posVec.begin()+firstBorderInd+1); - //reverse because canceled on ccw dir - std::reverse(posVec.begin(), posVec.end()); assert(posVec.size()==halfSize); } } From b39c768c05659d4b96dba739870a31c248124596 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Thu, 3 Dec 2020 18:26:56 +0100 Subject: [PATCH 040/140] removed point sampling from polygonal_algorithms --- vcg/complex/algorithms/polygonal_algorithms.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index a57625b9..7154278c 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include From 4b2455fad40969b2aa55771afc3653888df60f7f Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 11 Dec 2020 14:35:56 +1100 Subject: [PATCH 041/140] corrected ccw order of faces for border vertices --- vcg/simplex/face/topology.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vcg/simplex/face/topology.h b/vcg/simplex/face/topology.h index d17ca0f6..bd14e018 100644 --- a/vcg/simplex/face/topology.h +++ b/vcg/simplex/face/topology.h @@ -1194,7 +1194,8 @@ void VFOrderedStarFF(const Pos &startPos, { VFOrderedStarFF(startPos, posVec); const auto & pos = posVec[0]; - if (ccw != (pos.VFlip() == pos.F()->V(pos.F()->Prev(pos.VInd())))) + //if (ccw != (pos.VFlip() == pos.F()->V(pos.F()->Prev(pos.VInd())))) + if ((ccw) == (pos.V()!=pos.F()->V(pos.E()))) { std::reverse(posVec.begin(), posVec.end()); } From 0a0a06268fdbe412fd20d9bbd4f7b54f61a32625 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 11 Dec 2020 14:36:13 +1100 Subject: [PATCH 042/140] added globally rotation per vertex UV coordinates --- .../algorithms/parametrization/uv_utils.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/vcg/complex/algorithms/parametrization/uv_utils.h b/vcg/complex/algorithms/parametrization/uv_utils.h index cf43f9bd..6318310e 100644 --- a/vcg/complex/algorithms/parametrization/uv_utils.h +++ b/vcg/complex/algorithms/parametrization/uv_utils.h @@ -174,6 +174,23 @@ public: } } + static void GloballyRotatePerVert(MeshType &m,ScalarType Angle) + { + vcg::Box2 BB=PerVertUVBox(m); + UVCoordType Origin=BB.Center(); + typename MeshType::VertexIterator vi; + for (vi=m.vert.begin();vi!=m.vert.end();vi++) + { + if ((*vi).IsD()) continue; + (*vi).T().P()-=Origin; + ScalarType X1=(*vi).T().P().X()*cos(Angle)-(*vi).T().P().Y()*sin(Angle); + ScalarType Y1=(*vi).T().P().X()*cos(Angle)+(*vi).T().P().Y()*sin(Angle); + (*vi).T().P().X()=X1; + (*vi).T().P().Y()=Y1; + (*vi).T().P()+=Origin; + } + } + static void LaplacianUVVert(MeshType &m,bool fix_borders=false,int steps=3) { FaceIterator fi; From a8bda725fb23ba1f8ac9150f245b90a25902ee8e Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 11 Dec 2020 14:37:32 +1100 Subject: [PATCH 043/140] corrected star of faces around the borders so valence of singularities now is correct --- .../algorithms/parametrization/tangent_field_operators.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/parametrization/tangent_field_operators.h b/vcg/complex/algorithms/parametrization/tangent_field_operators.h index 5dd485b1..11a34442 100644 --- a/vcg/complex/algorithms/parametrization/tangent_field_operators.h +++ b/vcg/complex/algorithms/parametrization/tangent_field_operators.h @@ -1363,7 +1363,7 @@ public: std::vector > posVec; //SortedFaces(v,faces); face::Pos pos(v.cVFp(), v.cVFi()); - vcg::face::VFOrderedStarFF(pos, posVec); + vcg::face::VFOrderedStarFF(pos, posVec,true); int curr_dir=0; for (unsigned int i=0;i Date: Fri, 11 Dec 2020 16:53:15 +0100 Subject: [PATCH 044/140] templated face quality type --- vcg/simplex/face/component_ocf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index a09e84f7..2707dc22 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -370,7 +370,7 @@ public: std::vector CDV; std::vector MV; std::vector NV; - std::vector QV; + std::vector QV; std::vector WCV; std::vector WNV; std::vector WTV; From 313d9b14fffcd384b08630c59cbbb8a69ac3e3a9 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 11 Dec 2020 17:44:32 +0100 Subject: [PATCH 045/140] try to fix nonworking gh action --- wrap/qt/Outline2ToQImage.h | 1 + 1 file changed, 1 insertion(+) diff --git a/wrap/qt/Outline2ToQImage.h b/wrap/qt/Outline2ToQImage.h index 5d3b1b9c..f5e35650 100644 --- a/wrap/qt/Outline2ToQImage.h +++ b/wrap/qt/Outline2ToQImage.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include From 10af2ab4ae7b43e7644aa5d0212550017407d951 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Thu, 17 Dec 2020 00:12:45 +0100 Subject: [PATCH 046/140] corrected precision for saving floating point into ascii ply using nanoply --- wrap/nanoply/include/nanoply.hpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/wrap/nanoply/include/nanoply.hpp b/wrap/nanoply/include/nanoply.hpp index 10415db5..d35473a6 100644 --- a/wrap/nanoply/include/nanoply.hpp +++ b/wrap/nanoply/include/nanoply.hpp @@ -557,6 +557,30 @@ namespace nanoply return true; } + template <> + inline bool PlyFile::WriteAsciiData(const double & src) + { + if (mode != 1) + return false; + const auto precision = fileStream.precision(); + fileStream << std::setprecision(std::numeric_limits::max_digits10) + << src + << std::setprecision(precision); + return true; + } + + template <> + inline bool PlyFile::WriteAsciiData(const float & src) + { + if (mode != 1) + return false; + const auto precision = fileStream.precision(); + fileStream << std::setprecision(std::numeric_limits::max_digits10) + << src + << std::setprecision(precision); + return true; + } + inline void PlyFile::SetBufferSize(int64_t size) { maxSize = size; From ed5ae26e42eb6633e0974dadbc9b99cfa991c014 Mon Sep 17 00:00:00 2001 From: nico Date: Sat, 19 Dec 2020 17:22:42 +1100 Subject: [PATCH 047/140] changed minimal smooth ring to 3 in order to avoid not sufficient neighbors for curvature computation --- wrap/igl/smooth_field.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/igl/smooth_field.h b/wrap/igl/smooth_field.h index 6a3a6674..bc3ad19f 100644 --- a/wrap/igl/smooth_field.h +++ b/wrap/igl/smooth_field.h @@ -349,7 +349,7 @@ public: SmoothParam() { Ndir=4; - curvRing=2; + curvRing=3; alpha_curv=0.0; align_borders=false; SmoothM=SMMiq; From d991f12595a265165826fc38331a93f521d0d57e Mon Sep 17 00:00:00 2001 From: nico Date: Sat, 19 Dec 2020 17:23:29 +1100 Subject: [PATCH 048/140] made unique the list of seeds to start from for isotropic remeshing in case of adaptive meshing --- vcg/complex/algorithms/isotropic_remeshing.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vcg/complex/algorithms/isotropic_remeshing.h b/vcg/complex/algorithms/isotropic_remeshing.h index acea7280..c879a4af 100644 --- a/vcg/complex/algorithms/isotropic_remeshing.h +++ b/vcg/complex/algorithms/isotropic_remeshing.h @@ -379,6 +379,8 @@ private: tri::RequirePerVertexQuality(m); tri::UpdateTopology::FaceFace(m); // tri::UpdateFlags::VertexClearV(m); + for (size_t i=0;i seeds; ForEachFace(m, [&] (FaceType & f) { @@ -392,6 +394,10 @@ private: } }); + std::sort(seeds.begin(),seeds.end()); + auto last=std::unique(seeds.begin(),seeds.end()); + seeds.erase(last, seeds.end()); + tri::EuclideanDistance eu; tri::Geodesic::PerVertexDijkstraCompute(m, seeds, eu); tri::Smooth::VertexQualityLaplacian(m, 2); From 14239a798ac1bac5c82f68bd72b3672de68c4e06 Mon Sep 17 00:00:00 2001 From: korialis Date: Tue, 22 Dec 2020 19:21:58 +0100 Subject: [PATCH 049/140] adaptivity over inrad/circumrad, will later add choice for adaptivity field --- vcg/complex/algorithms/isotropic_remeshing.h | 82 ++++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/vcg/complex/algorithms/isotropic_remeshing.h b/vcg/complex/algorithms/isotropic_remeshing.h index c879a4af..4aff564d 100644 --- a/vcg/complex/algorithms/isotropic_remeshing.h +++ b/vcg/complex/algorithms/isotropic_remeshing.h @@ -283,9 +283,10 @@ public: { if(cb) cb(100*i/params.iter, "Remeshing"); + if (params.adapt) { - computeQualityDistFromCrease(toRemesh); + computeQualityDistFromRadii(toRemesh); tri::Smooth::VertexQualityLaplacian(toRemesh, 2); } @@ -405,9 +406,72 @@ private: ForEachVertex(m, [] (VertexType & v) { v.Q() = 1 / (v.Q() + 1); }); - } + static void computeQualityDistFromRadii(MeshType & m) + { + tri::RequirePerVertexQuality(m); + tri::RequirePerFaceQuality(m); + + ScalarType maxV = 0; + ScalarType minV = 10; + + ForEachFace(m, [&] (FaceType & f) { + f.Q() = 1. - vcg::QualityRadii(f.cP(0), f.cP(1), f.cP(2)); + maxV = std::max(maxV, f.Q()); + minV = std::min(minV, f.Q()); + }); + + //normalize + ForEachFace(m, [&] (FaceType & f) { + f.Q() = std::pow((f.Q() - minV) / (maxV - minV), 2.); + }); + + std::vector vertMax(m.VN(), 0); + std::vector vertMin(m.VN(), 10); + + ForEachFace(m, [&] (FaceType & f) { + for (int i = 0; i < 3; ++i) + { + auto vidx = vcg::tri::Index(m, f.V(i)); + vertMax[vidx] = std::max(vertMax[vidx], f.Q()); + vertMin[vidx] = std::min(vertMin[vidx], f.Q()); + } + }); + + for (size_t v = 0; v < m.VN(); ++v) + { + m.vert[v].Q() = vertMax[v] - vertMin[v]; + } + +// tri::UpdateQuality::VertexFromFace(m); + } + + static void computeQualityDistFromHeight(MeshType & m, const ScalarType lowerBound, const ScalarType higherBound) + { + tri::RequirePerVertexQuality(m); + tri::RequirePerFaceQuality(m); + + ScalarType maxV = 0; + ScalarType minV = 10; + + + ForEachFace(m, [&] (FaceType & f) { + ScalarType minH = std::numeric_limits::max(); + for (int i = 0; i < 3; ++i) + { + CoordType closest; + ScalarType dist = 0; + vcg::Segment3 seg(f.cP1(i), f.cP2(i)); + vcg::SegmentPointDistance(seg, f.cP0(i), closest, dist); + minH = std::min(minH, dist); + } + + f.Q() = math::Clamp(minH, lowerBound, higherBound); + }); + } + + /* Computes the ideal valence for the vertex in pos p: 4 for border vertices @@ -745,7 +809,10 @@ private: ScalarType length, lengthThr, minQ, maxQ; bool operator()(PosType &ep) { - ScalarType mult = math::ClampedLerp((ScalarType)0.25,(ScalarType)4, (((math::Abs(ep.V()->Q())+math::Abs(ep.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))); + ScalarType quality = (((math::Abs(ep.V()->Q())+math::Abs(ep.VFlip()->Q()))/(ScalarType)2.0)-minQ)/(maxQ-minQ); + ScalarType mult = math::ClampedLerp((ScalarType)0.4,(ScalarType)2.5, quality); +// ScalarType mult = 1; +// length = (ep.V()->Q() + ep.VFlip()->Q())/2.0; ScalarType dist = Distance(ep.V()->P(), ep.VFlip()->P()); if(dist > mult * length) { @@ -951,9 +1018,14 @@ private: static bool testCollapse1(PosType &p, VertexPair & pair, Point3 &mp, ScalarType minQ, ScalarType maxQ, Params ¶ms, bool relaxed = false) { - ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.25,(ScalarType)4, (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)/(maxQ-minQ))) : (ScalarType)1; - ScalarType dist = Distance(p.V()->P(), p.VFlip()->P()); + ScalarType quality = (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)-minQ)/(maxQ-minQ); + ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.4,(ScalarType)2.5, quality) : (ScalarType)1; ScalarType thr = mult*params.minLength; + +// ScalarType mult = 1; +// ScalarType thr = (p.V()->Q() + p.VFlip()->Q())/2.0; + + ScalarType dist = Distance(p.V()->P(), p.VFlip()->P()); ScalarType area = DoubleArea(*(p.F()))/2.f; if(relaxed || (dist < thr || area < params.minLength*params.minLength/100.f))//if to collapse { From 27a4ad3049bfdcb51a25b5b5a49d1149081f3109 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Wed, 23 Dec 2020 16:48:54 +0100 Subject: [PATCH 050/140] added VEStarVE overload returning also vertex indices --- vcg/simplex/edge/topology.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vcg/simplex/edge/topology.h b/vcg/simplex/edge/topology.h index 20688d78..6156a96d 100644 --- a/vcg/simplex/edge/topology.h +++ b/vcg/simplex/edge/topology.h @@ -75,6 +75,24 @@ void VEStarVE(const typename EdgeType::VertexType* vp, std::vector & } } +template +void VEStarVE(const typename EdgeType::VertexType * vp, + std::vector &starVec, + std::vector & indices) +{ + starVec.clear(); + indices.clear(); + starVec.reserve(16); + indices.reserve(16); + edge::VEIterator vei(vp); + while(!vei.End()) + { + starVec.push_back(vei.E()); + indices.push_back(vei.I()); + ++vei; + } +} + /// Completely detach an edge from the VE adjacency. Useful before deleting it template void VEDetach(EdgeType & e) From 37adbd64344088303d98f4dad2d14575e25380c5 Mon Sep 17 00:00:00 2001 From: korialis Date: Sat, 9 Jan 2021 12:36:35 +0100 Subject: [PATCH 051/140] slight mods to isotropic_remeshing --- vcg/complex/algorithms/isotropic_remeshing.h | 325 +++++++------------ 1 file changed, 113 insertions(+), 212 deletions(-) diff --git a/vcg/complex/algorithms/isotropic_remeshing.h b/vcg/complex/algorithms/isotropic_remeshing.h index 4aff564d..264e7c08 100644 --- a/vcg/complex/algorithms/isotropic_remeshing.h +++ b/vcg/complex/algorithms/isotropic_remeshing.h @@ -73,6 +73,9 @@ public: ScalarType maxLength; // maximal admitted length: no edge should be longer than this value (used when refining) ScalarType lengthThr; + ScalarType minAdaptiveMult = 1; + ScalarType maxAdaptiveMult = 1; + ScalarType minimalAdmittedArea; ScalarType maxSurfDist; @@ -277,7 +280,8 @@ public: tri::UpdateFlags::VertexBorderFromFaceAdj(toRemesh); tri::UpdateTopology::VertexFace(toRemesh); - tagCreaseEdges(toRemesh, params); + if (!params.userSelectedCreases) + tagCreaseEdges(toRemesh, params); for(int i=0; i < params.iter; ++i) { @@ -313,6 +317,69 @@ public: } } + static int tagCreaseEdges(MeshType &m, Params & params, bool forceTag = false) + { + int count = 0; + std::vector creaseVerts(m.VN(), 0); + + vcg::tri::UpdateFlags::VertexClearV(m); + std::queue creaseQueue; + + //if we are forcing the crease taggin or we are not using user creases...reset the faceedgeS... + if ((forceTag || !params.userSelectedCreases)) + vcg::tri::UpdateFlags::FaceClearFaceEdgeS(m); + + ForEachFacePos(m, [&](PosType &p){ + + if (p.IsBorder()) + p.F()->SetFaceEdgeS(p.E()); + + // if((p.F1Flip() > p.F())) + { + FaceType *ff = p.F(); + FaceType *ffAdj = p.FFlip(); + + double quality = vcg::QualityRadii(ff->cP(0), ff->cP(1), ff->cP(2)); + double qualityAdj = vcg::QualityRadii(ffAdj->cP(0), ffAdj->cP(1), ffAdj->cP(2)); + + bool qualityCheck = quality > 0.00000001 && qualityAdj > 0.00000001; + // bool areaCheck = vcg::DoubleArea(*ff) > 0.000001 && vcg::DoubleArea(*ffAdj) > 0.000001; + + if ((forceTag || !params.userSelectedCreases) && (testCreaseEdge(p, params.creaseAngleCosThr) /*&& areaCheck*//* && qualityCheck*/) || p.IsBorder()) + { + PosType pp = p; + std::vector faces; + std::vector edges; + bool allOk = true; + + do { + faces.push_back(pp.F()); + edges.push_back(pp.E()); + // pp.F()->SetFaceEdgeS(pp.E()); + if (vcg::QualityRadii(pp.F()->cP(0), pp.F()->cP(1), pp.F()->cP(2)) <= 0.0001) + { + allOk = false; + break; + } + pp.NextF(); + } while (pp != p); + + if (allOk) + { + for (int i = 0; i < faces.size(); ++i) + { + faces[i]->SetFaceEdgeS(edges[i]); + } + } + + creaseQueue.push(p); + } + } + }); + return count; + } + + private: /* TODO: Add better crease support: detect all creases at starting time, saving it on facedgesel flags @@ -347,6 +414,11 @@ private: minQ = distr.Percentile(0.1f); } + static inline ScalarType computeLengthThrMult(const Params & params, const ScalarType & quality) + { + return (params.adapt) ? math::ClampedLerp(params.minAdaptiveMult, params.maxAdaptiveMult, quality) : (ScalarType) 1; + } + //Computes PerVertexQuality as a function of the 'deviation' of the normals taken from //the faces incident to each vertex static void computeQuality(MeshType &m) @@ -517,160 +589,6 @@ private: return true; } - static int tagCreaseEdges(MeshType &m, Params & params) - { - int count = 0; - std::vector creaseVerts(m.VN(), 0); - - vcg::tri::UpdateFlags::VertexClearV(m); - std::queue creaseQueue; - - ForEachFacePos(m, [&](PosType &p){ - - if (p.IsBorder()) - p.F()->SetFaceEdgeS(p.E()); - - // if((p.FFlip() > p.F())) - { - FaceType *ff = p.F(); - FaceType *ffAdj = p.FFlip(); - - double quality = vcg::QualityRadii(ff->cP(0), ff->cP(1), ff->cP(2)); - double qualityAdj = vcg::QualityRadii(ffAdj->cP(0), ffAdj->cP(1), ffAdj->cP(2)); - - bool qualityCheck = quality > 0.00000001 && qualityAdj > 0.00000001; - // bool areaCheck = vcg::DoubleArea(*ff) > 0.000001 && vcg::DoubleArea(*ffAdj) > 0.000001; - - if (!params.userSelectedCreases && (testCreaseEdge(p, params.creaseAngleCosThr) /*&& areaCheck*//* && qualityCheck*/) || p.IsBorder()) - { - PosType pp = p; - std::vector faces; - std::vector edges; - bool allOk = true; - - do { - faces.push_back(pp.F()); - edges.push_back(pp.E()); - // pp.F()->SetFaceEdgeS(pp.E()); - if (vcg::QualityRadii(pp.F()->cP(0), pp.F()->cP(1), pp.F()->cP(2)) <= 0.0001) - { - allOk = false; - break; - } - pp.NextF(); - } while (pp != p); - - if (allOk) - { - for (int i = 0; i < faces.size(); ++i) - { - faces[i]->SetFaceEdgeS(edges[i]); - } - } - - creaseQueue.push(p); - } - } - }); - - // //now all creases are checked... - // //prune false positive (too small) (count + scale?) - - // while (!creaseQueue.empty()) - // { - // PosType & p = creaseQueue.front(); - // creaseQueue.pop(); - - // std::stack chainQueue; - // std::vector chainVerts; - - // if (!p.V()->IsV()) - // { - // chainQueue.push(p); - // } - - // p.FlipV(); - // p.NextEdgeS(); - - // if (!p.V()->IsV()) - // { - // chainQueue.push(p); - // } - - // while (!chainQueue.empty()) - // { - // PosType p = chainQueue.top(); - // chainQueue.pop(); - - // p.V()->SetV(); - // chainVerts.push_back(vcg::tri::Index(m, p.V())); - - // PosType pp = p; - - // //circle around vert in search for new crease edges - // do { - // pp.NextF(); //jump adj face - // pp.FlipE(); // this edge is already ok => jump to next - // if (pp.IsEdgeS()) - // { - // PosType nextPos = pp; - // nextPos.FlipV(); // go to next vert in the chain - // if (!nextPos.V()->IsV()) // if already visited...ignore - // { - // chainQueue.push(nextPos); - // } - // } - // } - // while (pp != p); - - // } - - // if (chainVerts.size() > 5) - // { - // for (auto vp : chainVerts) - // { - // creaseVerts[vp] = 1; - // } - // } - // } - // //store crease on V() - - // //this aspect ratio check doesn't work on cadish meshes (long thin triangles spanning whole mesh) - // ForEachFace(m, [&] (FaceType & f) { - // if (vcg::QualityRadii(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr) - // { - // if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) - // f.V(0)->SetS(); - // if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) - // f.V(1)->SetS(); - // if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) - // f.V(2)->SetS(); - // } - // }); - - // ForEachFace(m, [&] (FaceType & f) { - // for (int i = 0; i < 3; ++i) - // { - // if (f.FFp(i) > &f) - // { - // ScalarType angle = fastAngle(NormalizedTriangleNormal(f), NormalizedTriangleNormal(*(f.FFp(i)))); - // if (angle <= params.foldAngleCosThr) - // { - // // if (creaseVerts[vcg::tri::Index(m, f.V0(i))] == 0) - // f.V0(i)->SetS(); - // // if (creaseVerts[vcg::tri::Index(m, f.V1(i))] == 0) - // f.V1(i)->SetS(); - // // if (creaseVerts[vcg::tri::Index(m, f.V2(i))] == 0) - // f.V2(i)->SetS(); - // // if (creaseVerts[vcg::tri::Index(m, f.FFp(i)->V2(f.FFi(i)))] == 0) - // f.FFp(i)->V2(f.FFi(i))->SetS(); - // } - // } - // } - // }); - - return count; - } /* @@ -773,8 +691,9 @@ private: face::IsManifold(f, i) && /*checkManifoldness(f, i) &&*/ face::checkFlipEdgeNotManifold(f, i) && testSwap(pi, params.creaseAngleCosThr) && - (!params.surfDistCheck || testHausdorff(*params.mProject, params.grid, toCheck, params.maxSurfDist)) && - face::CheckFlipEdgeNormal(f, i, vcg::math::ToRad(5.))) +// face::CheckFlipEdge(f, i) && + face::CheckFlipEdgeNormal(f, i, params.creaseAngleRadThr) && //vcg::math::ToRad(5.)) && + (!params.surfDistCheck || testHausdorff(*params.mProject, params.grid, toCheck, params.maxSurfDist))) { //When doing the swap we need to preserve and update the crease info accordingly FaceType* g = f.cFFp(i); @@ -807,12 +726,14 @@ private: public: int count = 0; ScalarType length, lengthThr, minQ, maxQ; + const Params & params; + + EdgeSplitAdaptPred(const Params & p) : params(p) {}; + bool operator()(PosType &ep) { ScalarType quality = (((math::Abs(ep.V()->Q())+math::Abs(ep.VFlip()->Q()))/(ScalarType)2.0)-minQ)/(maxQ-minQ); - ScalarType mult = math::ClampedLerp((ScalarType)0.4,(ScalarType)2.5, quality); -// ScalarType mult = 1; -// length = (ep.V()->Q() + ep.VFlip()->Q())/2.0; + ScalarType mult = computeLengthThrMult(params, quality); ScalarType dist = Distance(ep.V()->P(), ep.VFlip()->P()); if(dist > mult * length) { @@ -851,12 +772,12 @@ private: ScalarType minQ,maxQ; if(params.adapt){ computeVQualityDistrMinMax(m, minQ, maxQ); - EdgeSplitAdaptPred ep; + EdgeSplitAdaptPred ep(params); ep.minQ = minQ; ep.maxQ = maxQ; ep.length = params.maxLength; ep.lengthThr = params.lengthThr; - tri::RefineMidpoint(m,ep, params.selectedOnly); + tri::RefineMidpoint(m, ep, params.selectedOnly); params.stat.splitNum+=ep.count; } else { @@ -947,11 +868,8 @@ private: Point3 oldN = NormalizedTriangleNormal(*(pi.F())); Point3 newN = Normal(mp, v1->P(), v2->P()).Normalize(); - // float div = fastAngle(oldN, newN); - // if(div < .9f ) return false; - if (oldN * newN < 0.5f) - return false; - +// if (oldN * newN < 0.5f) +// return false; std::vector baryP(1); baryP[0] = (v1->cP() + v2->cP() + mp) / 3.; @@ -1019,12 +937,9 @@ private: static bool testCollapse1(PosType &p, VertexPair & pair, Point3 &mp, ScalarType minQ, ScalarType maxQ, Params ¶ms, bool relaxed = false) { ScalarType quality = (((math::Abs(p.V()->Q())+math::Abs(p.VFlip()->Q()))/(ScalarType)2.0)-minQ)/(maxQ-minQ); - ScalarType mult = (params.adapt) ? math::ClampedLerp((ScalarType)0.4,(ScalarType)2.5, quality) : (ScalarType)1; + ScalarType mult = computeLengthThrMult(params, quality); ScalarType thr = mult*params.minLength; -// ScalarType mult = 1; -// ScalarType thr = (p.V()->Q() + p.VFlip()->Q())/2.0; - ScalarType dist = Distance(p.V()->P(), p.VFlip()->P()); ScalarType area = DoubleArea(*(p.F()))/2.f; if(relaxed || (dist < thr || area < params.minLength*params.minLength/100.f))//if to collapse @@ -1318,20 +1233,6 @@ private: }); - //this aspect ratio check doesn't work on cadish meshes (long thin triangles spanning whole mesh) - // ForEachFace(m, [&] (FaceType & f) { - // if (vcg::Quality(f.cP(0), f.cP(1), f.cP(2)) < params.aspectRatioThr || vcg::DoubleArea(f) < 0.00001) - // { - // if (creaseVerts[vcg::tri::Index(m, f.V(0))] == 0) - // f.V(0)->SetS(); - // if (creaseVerts[vcg::tri::Index(m, f.V(1))] == 0) - // f.V(1)->SetS(); - // if (creaseVerts[vcg::tri::Index(m, f.V(2))] == 0) - // f.V(2)->SetS(); - // } - // }); - - ForEachFace(m, [&] (FaceType & f) { for (int i = 0; i < 3; ++i) { @@ -1419,33 +1320,33 @@ private: TD[*vi].sum = ((*vi).P() + TD[*vi].sum) / (TD[*vi].cnt + 1); } - for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) - { - if (!(*fi).IsD()) - { - for (int j = 0; j < 3; ++j) - { - if (Angle(Normal(TD[(*fi).V0(j)].sum, (*fi).P1(j), (*fi).P2(j)), - Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) - TD[(*fi).V0(j)].sum = (*fi).P0(j); - } - } - } - for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) - { - if (!(*fi).IsD()) - { - for (int j = 0; j < 3; ++j) - { - if (Angle(Normal(TD[(*fi).V0(j)].sum, TD[(*fi).V1(j)].sum, (*fi).P2(j)), - Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) - { - TD[(*fi).V0(j)].sum = (*fi).P0(j); - TD[(*fi).V1(j)].sum = (*fi).P1(j); - } - } - } - } +// for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) +// { +// if (!(*fi).IsD()) +// { +// for (int j = 0; j < 3; ++j) +// { +// if (Angle(Normal(TD[(*fi).V0(j)].sum, (*fi).P1(j), (*fi).P2(j)), +// Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) +// TD[(*fi).V0(j)].sum = (*fi).P0(j); +// } +// } +// } +// for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) +// { +// if (!(*fi).IsD()) +// { +// for (int j = 0; j < 3; ++j) +// { +// if (Angle(Normal(TD[(*fi).V0(j)].sum, TD[(*fi).V1(j)].sum, (*fi).P2(j)), +// Normal((*fi).P0(j), (*fi).P1(j), (*fi).P2(j))) > M_PI/2.) +// { +// TD[(*fi).V0(j)].sum = (*fi).P0(j); +// TD[(*fi).V1(j)].sum = (*fi).P1(j); +// } +// } +// } +// } for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi) if (!(*vi).IsD() && TD[*vi].cnt > 0) From c4cb66234ba5bb982c3c25f55a9b1286c147f3c2 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Sun, 10 Jan 2021 02:04:04 +0100 Subject: [PATCH 052/140] minor changes to RotationMatrix of Matrix33 --- vcg/math/matrix33.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/vcg/math/matrix33.h b/vcg/math/matrix33.h index 5c82526d..2da2c504 100644 --- a/vcg/math/matrix33.h +++ b/vcg/math/matrix33.h @@ -574,16 +574,12 @@ Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=t ///return the rotation matrix along axis template Matrix33 RotationMatrix(const vcg::Point3 &axis, - const float &angleRad) - { - vcg::Matrix44 matr44; - vcg::Matrix33 matr33; - matr44.SetRotateRad(angleRad,axis); - for (int i=0;i<3;i++) - for (int j=0;j<3;j++) - matr33[i][j]=matr44[i][j]; - return matr33; - } + const S &angleRad) +{ + vcg::Matrix44 matr44; + matr44.SetRotateRad(angleRad,axis); + return vcg::Matrix33(matr44, 3); +} /// return a random rotation matrix, from the paper: /// Fast Random Rotation Matrices, James Arvo From 89997b915f116a3daa6ddc4665aaec2593fe5632 Mon Sep 17 00:00:00 2001 From: nico Date: Mon, 11 Jan 2021 23:19:04 +1100 Subject: [PATCH 053/140] corrected some interpolation numerical issue in InterpolateField3D --- .../parametrization/tangent_field_operators.h | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/vcg/complex/algorithms/parametrization/tangent_field_operators.h b/vcg/complex/algorithms/parametrization/tangent_field_operators.h index 11a34442..4dfb3963 100644 --- a/vcg/complex/algorithms/parametrization/tangent_field_operators.h +++ b/vcg/complex/algorithms/parametrization/tangent_field_operators.h @@ -110,31 +110,35 @@ vcg::Point3 InterpolateNRosy3D(const std::vector-0.99999) + { + //std::cout << "V[i] " << V[i].X() << " " << V[i].Y() << std::endl << std::flush; - ///rotate the vector to become tangent to the reference plane - vcg::Matrix33 RotNorm=vcg::RotationMatrix(Norm[i],TargetN); - //std::cout << "Norm[i] " << Norm[i].X() << " " << Norm[i].Y() << " " << Norm[i].Z()<< std::endl; - //std::cout << "TargetN " << TargetN.X() << " " << TargetN.Y() << " " << TargetN.Z()<< std::endl<< std::flush; + ///rotate the vector to become tangent to the reference plane + vcg::Matrix33 RotNorm=vcg::RotationMatrix(Norm[i],TargetN); +// std::cout << "Norm[i] " << Norm[i].X() << " " << Norm[i].Y() << " " << Norm[i].Z()<< std::endl; +// std::cout << "TargetN " << TargetN.X() << " " << TargetN.Y() << " " << TargetN.Z()<< std::endl<< std::flush; - CoordType rotV=RotNorm*V[i]; - //assert(fabs(rotV*TargetN)<0.000001); - rotV.Normalize(); - //std::cout << "rotV " << rotV.X() << " " << rotV.Y() << " " << rotV.Z()<< std::endl<< std::flush; + rotV=RotNorm*V[i]; + //assert(fabs(rotV*TargetN)<0.000001); + rotV.Normalize(); + //std::cout << "rotV " << rotV.X() << " " << rotV.Y() << " " << rotV.Z()<< std::endl<< std::flush; - ///trassform to the reference frame - rotV=RotFrame*rotV; -// if (isnan(rotV.X())||isnan(rotV.Y())) -// { -// std::cout << "V[i] " << V[i].X() << " " << V[i].Y() << std::endl << std::flush; -// std::cout << "Norm[i] " << Norm[i].X() << " " << Norm[i].Y() << " " << Norm[i].Z()<< std::endl; -// std::cout << "TargetN " << TargetN.X() << " " << TargetN.Y() << " " << TargetN.Z()<< std::endl<< std::flush; -// } - - assert(!isnan(rotV.X())); - assert(!isnan(rotV.Y())); + ///trassform to the reference frame + rotV=RotFrame*rotV; + // if (isnan(rotV.X())||isnan(rotV.Y())) + // { + // std::cout << "V[i] " << V[i].X() << " " << V[i].Y() << std::endl << std::flush; + // std::cout << "Norm[i] " << Norm[i].X() << " " << Norm[i].Y() << " " << Norm[i].Z()<< std::endl; + // std::cout << "TargetN " << TargetN.X() << " " << TargetN.Y() << " " << TargetN.Z()<< std::endl<< std::flush; + // } + assert(!isnan(rotV.X())); + assert(!isnan(rotV.Y())); + } //it's 2D from now on Cross2D.push_back(vcg::Point2(rotV.X(),rotV.Y())); @@ -534,9 +538,9 @@ public: static void InitBorderField(MeshType & mesh) { typedef typename MeshType::FaceType FaceType; -// typedef typename MeshType::VertexType VertexType; + // typedef typename MeshType::VertexType VertexType; typedef typename MeshType::CoordType CoordType; -// typedef typename MeshType::ScalarType ScalarType; + // typedef typename MeshType::ScalarType ScalarType; vcg::tri::UpdateTopology::FaceFace(mesh); for (size_t i=0;i::FaceClearS(mesh); for (int i=0; i<(int)Sel0.size(); i++) - mesh.face[Sel0[i]].SetS(); + mesh.face[Sel0[i]].SetS(); } static size_t FindSeparatrices(const typename vcg::face::Pos &vPos, From f1fce45d929a31c003ddaeddd340ef6e6c4a697b Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 21 Jan 2021 14:45:05 +0100 Subject: [PATCH 054/140] toEigenMatrix functions matrix33 and matrix44 --- vcg/math/matrix33.h | 11 +++++++++++ vcg/math/matrix44.h | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/vcg/math/matrix33.h b/vcg/math/matrix33.h index 2da2c504..356a10db 100644 --- a/vcg/math/matrix33.h +++ b/vcg/math/matrix33.h @@ -75,6 +75,15 @@ public: m(i,j)=(*this)[i][j]; } + template + EigenMatrix33Type ToEigenMatrix() const { + EigenMatrix33Type m; + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + m(i,j)=(*this)[i][j]; + return m; + } + template void FromEigenMatrix(const EigenMatrix33Type & m){ for(int i = 0; i < 3; i++) @@ -82,6 +91,8 @@ public: (*this)[i][j]=m(i,j); } + + static inline const Matrix33 &Identity( ) { static Matrix33 tmp; tmp.SetIdentity(); diff --git a/vcg/math/matrix44.h b/vcg/math/matrix44.h index 7ca46188..cb2f8c7c 100644 --- a/vcg/math/matrix44.h +++ b/vcg/math/matrix44.h @@ -158,6 +158,15 @@ public: m(i,j)=(*this)[i][j]; } + template + EigenMatrix44Type ToEigenMatrix() const { + EigenMatrix44Type m; + for(int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++) + m(i,j)=(*this)[i][j]; + return m; + } + template void FromEigenMatrix(const EigenMatrix44Type & m){ for(int i = 0; i < 4; i++) From 4b387c3f670c39241e9a5891bb0081c4dd923dc8 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 26 Jan 2021 12:50:29 +0100 Subject: [PATCH 055/140] const correctness for user defined mesh attributes --- vcg/complex/allocate.h | 104 ++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 16 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 9a75492b..5ada3e88 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1427,8 +1427,8 @@ public: */ template static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerVertexAttributeHandle & a){ - if(a._handle == NULL) return false; + bool IsValidHandle( const MeshType & m, const typename MeshType::template PerVertexAttributeHandle & a){ + if(a._handle == nullptr) return false; for(AttrIterator i = m.vert_attr.begin(); i!=m.vert_attr.end();++i) if ( (*i).n_attr == a.n_attr ) return true; return false; @@ -1482,6 +1482,21 @@ public: } return AddPerVertexAttribute(m,name); } + + /*! \brief gives a handle to a per-vertex attribute with a given name and ATTR_TYPE + \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. + Otherwise, returns an invalid handle (check it using IsValidHandle). + */ + template + static + typename MeshType::template PerVertexAttributeHandle + GetPerVertexAttribute( const MeshType & m, std::string name = std::string("")){ + typename MeshType::template PerVertexAttributeHandle h; + if(!name.empty()){ + return FindPerVertexAttribute(m,name); + } + return typename MeshType:: template PerVertexAttributeHandle(nullptr,0); + } /*! \brief Try to retrieve an handle to an attribute with a given name and ATTR_TYPE \returns a invalid handle if no attribute with that name and type exists. @@ -1507,7 +1522,28 @@ public: } return typename MeshType::template PerVertexAttributeHandle((*i)._handle,(*i).n_attr); } - return typename MeshType:: template PerVertexAttributeHandle(NULL,0); + return typename MeshType:: template PerVertexAttributeHandle(nullptr,0); + } + + /** + * Same as the one above, but without modifying the attribute if it is found. + * (A "find" function should never modify the container in which is looking for..) + * Input mesh is const. + */ + template + static typename MeshType::template PerVertexAttributeHandle + FindPerVertexAttribute( const MeshType & m, const std::string & name) + { + assert(!name.empty()); + PointerToAttribute h1; h1._name = name; + typename std::set :: iterator i; + + i =m.vert_attr.find(h1); + if(i!=m.vert_attr.end()) + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + return typename MeshType::template PerVertexAttributeHandle((*i)._handle,(*i).n_attr); + } + return typename MeshType:: template PerVertexAttributeHandle(nullptr,0); } /*! \brief query the mesh for all the attributes per vertex @@ -1573,8 +1609,8 @@ public: /// Per Edge Attributes template static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerEdgeAttributeHandle & a){ - if(a._handle == NULL) return false; + bool IsValidHandle( const MeshType & m, const typename MeshType::template PerEdgeAttributeHandle & a){ + if(a._handle == nullptr) return false; for(AttrIterator i = m.edge_attr.begin(); i!=m.edge_attr.end();++i) if ( (*i).n_attr == a.n_attr ) return true; return false; @@ -1649,7 +1685,7 @@ public: return typename MeshType::template PerEdgeAttributeHandle((*i)._handle,(*i).n_attr); } - return typename MeshType:: template PerEdgeAttributeHandle(NULL,0); + return typename MeshType:: template PerEdgeAttributeHandle(nullptr,0); } template @@ -1697,8 +1733,8 @@ public: /// Per Face Attributes template static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerFaceAttributeHandle & a){ - if(a._handle == NULL) return false; + bool IsValidHandle( const MeshType & m, const typename MeshType::template PerFaceAttributeHandle & a){ + if(a._handle == nullptr) return false; for(AttrIterator i = m.face_attr.begin(); i!=m.face_attr.end();++i) if ( (*i).n_attr == a.n_attr ) return true; return false; @@ -1733,7 +1769,7 @@ public: return AddPerFaceAttribute(m,std::string("")); } - /*! \brief gives a handle to a per-edge attribute with a given name and ATTR_TYPE + /*! \brief gives a handle to a per-face attribute with a given name and ATTR_TYPE \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. Otherwise return a hanlde to a newly created. */ @@ -1749,6 +1785,21 @@ public: } return AddPerFaceAttribute(m,name); } + + /*! \brief gives a handle to a per-face attribute with a given name and ATTR_TYPE + \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. + Otherwise, returns an invalid handle (check it using IsValidHandle). + */ + template + static + typename MeshType::template PerFaceAttributeHandle + GetPerFaceAttribute( const MeshType & m, std::string name = std::string("")){ + typename MeshType::template PerFaceAttributeHandle h; + if(!name.empty()){ + return FindPerFaceAttribute(m,name); + } + return typename MeshType:: template PerFaceAttributeHandle(nullptr,0); + } template static @@ -1771,7 +1822,28 @@ public: } return typename MeshType::template PerFaceAttributeHandle((*i)._handle,(*i).n_attr); } - return typename MeshType:: template PerFaceAttributeHandle(NULL,0); + return typename MeshType:: template PerFaceAttributeHandle(nullptr,0); + } + + /** + * Same as the one above, but without modifying the attribute if it is found. + * (A "find" function should never modify the container in which is looking for..) + * Input mesh is const. + */ + template + static + typename MeshType::template PerFaceAttributeHandle + FindPerFaceAttribute( const MeshType & m, const std::string & name){ + assert(!name.empty()); + PointerToAttribute h1; h1._name = name; + typename std::set ::iterator i; + + i =m.face_attr.find(h1); + if(i!=m.face_attr.end()) + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + return typename MeshType::template PerFaceAttributeHandle((*i)._handle,(*i).n_attr); + } + return typename MeshType:: template PerFaceAttributeHandle(nullptr,0); } template @@ -1816,9 +1888,9 @@ public: /// Per Tetra Attributes template - static bool IsValidHandle(MeshType & m, const typename MeshType::template PerTetraAttributeHandle & a) + static bool IsValidHandle(const MeshType & m, const typename MeshType::template PerTetraAttributeHandle & a) { - if (a._handle == NULL) + if (a._handle == nullptr) return false; for (AttrIterator i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i) if ((*i).n_attr == a.n_attr) @@ -1894,7 +1966,7 @@ public: } return typename MeshType::template PerTetraAttributeHandle((*i)._handle, (*i).n_attr); } - return typename MeshType::template PerTetraAttributeHandle(NULL, 0); + return typename MeshType::template PerTetraAttributeHandle(nullptr, 0); } template @@ -1947,8 +2019,8 @@ public: /// Per Mesh Attributes template static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerMeshAttributeHandle & a){ - if(a._handle == NULL) return false; + bool IsValidHandle(const MeshType & m, const typename MeshType::template PerMeshAttributeHandle & a){ + if(a._handle == nullptr) return false; for(AttrIterator i = m.mesh_attr.begin(); i!=m.mesh_attr.end();++i) if ( (*i).n_attr == a.n_attr ) return true; return false; @@ -2015,7 +2087,7 @@ public: return typename MeshType::template PerMeshAttributeHandle((*i)._handle,(*i).n_attr); } - return typename MeshType:: template PerMeshAttributeHandle(NULL,0); + return typename MeshType:: template PerMeshAttributeHandle(nullptr,0); } template From 280245b70bfa5dc7cea4565349d170cdfe58c87e Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 28 Jan 2021 12:46:13 +0100 Subject: [PATCH 056/140] hardcoded floats to Scalar; fix some warnings (#158) --- vcg/complex/algorithms/create/plymc/plymc.h | 2 +- vcg/complex/algorithms/pointcloud_normal.h | 10 ++++---- vcg/space/index/kdtree/kdtree.h | 26 ++++++++++----------- wrap/io_trimesh/import_asc.h | 2 +- wrap/io_trimesh/import_dae.h | 14 +++++------ 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/vcg/complex/algorithms/create/plymc/plymc.h b/vcg/complex/algorithms/create/plymc/plymc.h index ae268ef5..d01ed870 100644 --- a/vcg/complex/algorithms/create/plymc/plymc.h +++ b/vcg/complex/algorithms/create/plymc/plymc.h @@ -340,7 +340,7 @@ public: bool Process(vcg::CallBackPos *cb=0) { - sprintf(errorMessage,""); + sprintf(errorMessage,"%s", ""); printf("bbox scanning...\n"); fflush(stdout); Matrix44f Id; Id.SetIdentity(); MP.InitBBox(); diff --git a/vcg/complex/algorithms/pointcloud_normal.h b/vcg/complex/algorithms/pointcloud_normal.h index 87a748e2..2be75193 100644 --- a/vcg/complex/algorithms/pointcloud_normal.h +++ b/vcg/complex/algorithms/pointcloud_normal.h @@ -49,11 +49,11 @@ public: class WArc { public: - WArc(VertexPointer _s,VertexPointer _t):src(_s),trg(_t),w(fabs(_s->cN()*_t->cN())){} + WArc(VertexPointer _s,VertexPointer _t):src(_s),trg(_t),w(std::abs(_s->cN()*_t->cN())){} VertexPointer src; VertexPointer trg; - float w; + ScalarType w; bool operator< (const WArc &a) const {return wN().dot(p.viewPoint- vi->P())<0.0f) + if ( vi->N().dot(p.viewPoint- vi->P())<0.0) vi->N()=-(*vi).N(); } return; @@ -175,7 +175,7 @@ public: if(!a.trg->IsV()) { a.trg->SetV(); - if(a.src->cN()*a.trg->cN()<0.0f) + if(a.src->cN()*a.trg->cN()<0.0) a.trg->N()=-a.trg->N(); AddNeighboursToHeap(m,a.trg,p.coherentAdjNum,tree,heap); } diff --git a/vcg/space/index/kdtree/kdtree.h b/vcg/space/index/kdtree/kdtree.h index 51ddc574..a143fe9d 100755 --- a/vcg/space/index/kdtree/kdtree.h +++ b/vcg/space/index/kdtree/kdtree.h @@ -123,7 +123,7 @@ namespace vcg { void doQueryK(const VectorType& queryPoint, int k, PriorityQueue& mNeighborQueue); - void doQueryDist(const VectorType& queryPoint, float dist, std::vector& points, std::vector& sqrareDists); + void doQueryDist(const VectorType& queryPoint, Scalar dist, std::vector& points, std::vector& sqrareDists); void doQueryClosest(const VectorType& queryPoint, unsigned int& index, Scalar& dist); @@ -140,7 +140,7 @@ namespace vcg { // used to build the tree: split the subset [start..end[ according to dim and splitValue, // and returns the index of the first element of the second subset - unsigned int split(int start, int end, unsigned int dim, float splitValue); + unsigned int split(int start, int end, unsigned int dim, Scalar splitValue); int createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level); @@ -211,7 +211,7 @@ namespace vcg { std::vector mNodeStack(numLevel + 1); mNodeStack[0].nodeId = 0; - mNodeStack[0].sq = 0.f; + mNodeStack[0].sq = 0.; unsigned int count = 1; while (count) @@ -242,7 +242,7 @@ namespace vcg { else { // the new offset is the distance between the searched point and the actual split coordinate - float new_off = queryPoint[node.dim] - node.splitValue; + Scalar new_off = queryPoint[node.dim] - node.splitValue; //left sub-tree if (new_off < 0.) @@ -279,14 +279,14 @@ namespace vcg { * and the vector of the squared distances from the query point. */ template - void KdTree::doQueryDist(const VectorType& queryPoint, float dist, std::vector& points, std::vector& sqrareDists) + void KdTree::doQueryDist(const VectorType& queryPoint, Scalar dist, std::vector& points, std::vector& sqrareDists) { std::vector mNodeStack(numLevel + 1); mNodeStack[0].nodeId = 0; - mNodeStack[0].sq = 0.f; + mNodeStack[0].sq = 0.; unsigned int count = 1; - float sqrareDist = dist*dist; + Scalar sqrareDist = dist*dist; while (count) { QueryNode& qnode = mNodeStack[count - 1]; @@ -300,7 +300,7 @@ namespace vcg { unsigned int end = node.start + node.size; for (unsigned int i = node.start; i < end; ++i) { - float pointSquareDist = vcg::SquaredNorm(queryPoint - mPoints[i]); + Scalar pointSquareDist = vcg::SquaredNorm(queryPoint - mPoints[i]); if (pointSquareDist < sqrareDist) { points.push_back(mIndices[i]); @@ -311,7 +311,7 @@ namespace vcg { else { // replace the stack top by the farthest and push the closest - float new_off = queryPoint[node.dim] - node.splitValue; + Scalar new_off = queryPoint[node.dim] - node.splitValue; if (new_off < 0.) { mNodeStack[count].nodeId = node.firstChildId; @@ -346,7 +346,7 @@ namespace vcg { { std::vector mNodeStack(numLevel + 1); mNodeStack[0].nodeId = 0; - mNodeStack[0].sq = 0.f; + mNodeStack[0].sq = 0.; unsigned int count = 1; int minIndex = mIndices.size() / 2; @@ -366,7 +366,7 @@ namespace vcg { unsigned int end = node.start + node.size; for (unsigned int i = node.start; i < end; ++i) { - float pointSquareDist = vcg::SquaredNorm(queryPoint - mPoints[i]); + Scalar pointSquareDist = vcg::SquaredNorm(queryPoint - mPoints[i]); if (pointSquareDist < minDist) { minDist = pointSquareDist; @@ -377,7 +377,7 @@ namespace vcg { else { // replace the stack top by the farthest and push the closest - float new_off = queryPoint[node.dim] - node.splitValue; + Scalar new_off = queryPoint[node.dim] - node.splitValue; if (new_off < 0.) { mNodeStack[count].nodeId = node.firstChildId; @@ -411,7 +411,7 @@ namespace vcg { * using the "dim" coordinate [0 = x, 1 = y, 2 = z]. */ template - unsigned int KdTree::split(int start, int end, unsigned int dim, float splitValue) + unsigned int KdTree::split(int start, int end, unsigned int dim, Scalar splitValue) { int l(start), r(end - 1); for (; l < r; ++l, --r) diff --git a/wrap/io_trimesh/import_asc.h b/wrap/io_trimesh/import_asc.h index e72bec86..b480bfb5 100644 --- a/wrap/io_trimesh/import_asc.h +++ b/wrap/io_trimesh/import_asc.h @@ -139,7 +139,7 @@ static int Open( MESH_TYPE &m, const char * filename, CallBackPos *cb=0, bool tr if(m.vert[i].P().Y()!= baseY) break; } cnt=m.vert.size(); - qDebug("Grid is %i x %i = %i (%zu) ",i,cnt/i,i* (cnt/i),cnt); + qDebug("Grid is %i x %li = %li (%zu) ",i,cnt/i,i* (cnt/i),cnt); tri::FaceGrid(m,i,int(cnt/i)); tri::Clean::FlipMesh(m); return E_NOERROR; diff --git a/wrap/io_trimesh/import_dae.h b/wrap/io_trimesh/import_dae.h index 00a8549d..b4e0e09b 100644 --- a/wrap/io_trimesh/import_dae.h +++ b/wrap/io_trimesh/import_dae.h @@ -186,7 +186,7 @@ namespace io { static DAEError LoadPolygonalListMesh(QDomNodeList& polylist,ColladaMesh& m,const size_t offset,InfoDAE& info,QMap &materialBinding) { if(polylist.isEmpty()) return E_NOERROR; - QDEBUG("****** LoadPolygonalListMesh (initial mesh size %i %i)",m.vert.size(),m.fn); + QDEBUG("****** LoadPolygonalListMesh (initial mesh size %li %i)",m.vert.size(),m.fn); for(int tript = 0; tript < polylist.size();++tript) { QString materialId = polylist.at(tript).toElement().attribute(QString("material")); @@ -271,7 +271,7 @@ namespace io { } } - QDEBUG("****** LoadPolygonalListMesh (final mesh size vn %i vertsize %i - fn %i facesize %i)",m.vn,m.vert.size(),m.fn,m.face.size()); + QDEBUG("****** LoadPolygonalListMesh (final mesh size vn %i vertsize %li - fn %i facesize %li)",m.vn,m.vert.size(),m.fn,m.face.size()); return E_NOERROR; } @@ -435,12 +435,12 @@ namespace io { if( ! ( (m.face[ff].V(0) != m.face[ff].V(1)) && (m.face[ff].V(0) != m.face[ff].V(2)) && (m.face[ff].V(1) != m.face[ff].V(2)) ) ) - QDEBUG("********* WARNING face %i, (%i %i %i) is a DEGENERATE FACE!",ff, m.face[ff].V(0) - &m.vert.front(), m.face[ff].V(1) - &m.vert.front(), m.face[ff].V(2) - &m.vert.front()); + QDEBUG("********* WARNING face %i, (%li %li %li) is a DEGENERATE FACE!",ff, m.face[ff].V(0) - &m.vert.front(), m.face[ff].V(1) - &m.vert.front(), m.face[ff].V(2) - &m.vert.front()); } } } - QDEBUG("****** LoadTriangularMesh (final mesh size %i %i - %i %i)",m.vn,m.vert.size(),m.fn,m.face.size()); + QDEBUG("****** LoadTriangularMesh (final mesh size %i %li - %i %li)",m.vn,m.vert.size(),m.fn,m.face.size()); return E_NOERROR; } @@ -602,7 +602,7 @@ namespace io { if (err != E_NOERROR) return err; } - QDEBUG("**** Loading a Geometry Mesh **** (final mesh size %i %i - %i %i)",m.vn,m.vert.size(),m.fn,m.face.size()); + QDEBUG("**** Loading a Geometry Mesh **** (final mesh size %i %li - %i %li)",m.vn,m.vert.size(),m.fn,m.face.size()); return E_NOERROR; } @@ -637,7 +637,7 @@ namespace io { QDomElement instGeomNode= geomNodeList.at(ch).toElement(); if(instGeomNode.parentNode()==node) // process only direct child { - QDEBUG("** instance_geometry with url %s (initial mesh size %i %i T = %i)",qPrintable(instGeomNode.attribute("url")),m.vn,m.fn,m.textures.size()); + QDEBUG("** instance_geometry with url %s (initial mesh size %i %i T = %li)",qPrintable(instGeomNode.attribute("url")),m.vn,m.fn,m.textures.size()); //assert(m.textures.size()>0 == HasPerWedgeTexCoord(m)); QString geomNode_url; referenceToANodeAttribute(instGeomNode,"url",geomNode_url); @@ -654,7 +654,7 @@ namespace io { LoadGeometry(newMesh, info, refNode.toElement(),materialBindingMap); tri::UpdatePosition::Matrix(newMesh,curTr); tri::Append::Mesh(m,newMesh); - QDEBUG("** instance_geometry with url %s (final mesh size %i %i - %i %i)",qPrintable(instGeomNode.attribute("url")),m.vn,m.vert.size(),m.fn,m.face.size()); + QDEBUG("** instance_geometry with url %s (final mesh size %i %li - %i %li)",qPrintable(instGeomNode.attribute("url")),m.vn,m.vert.size(),m.fn,m.face.size()); } } From 4bc6e679d241b72199787f160edf30401b80cb17 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 28 Jan 2021 12:50:05 +0100 Subject: [PATCH 057/140] actions - mirror for jom download for windows --- .github/workflows/BuildSamplesWindows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/BuildSamplesWindows.yml b/.github/workflows/BuildSamplesWindows.yml index fe07665d..a9a069b0 100644 --- a/.github/workflows/BuildSamplesWindows.yml +++ b/.github/workflows/BuildSamplesWindows.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v2 - name: Download Jom run: | - Invoke-WebRequest -Uri "http://download.qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" + Invoke-WebRequest -Uri "http://mirrors.ukfast.co.uk/sites/qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" New-Item -Name "jom" -ItemType "directory" Expand-Archive -Path jom_1_1_3.zip -DestinationPath .\jom echo "$(Get-Location)\jom" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append From de8569a483c25ef3f5044adc1a92376f6dfa408f Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 28 Jan 2021 21:30:24 +0100 Subject: [PATCH 058/140] random const correctness --- vcg/complex/algorithms/inertia.h | 9 +++--- vcg/complex/algorithms/stat.h | 49 ++++++++++++++++---------------- vcg/simplex/face/component.h | 5 ++++ 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/vcg/complex/algorithms/inertia.h b/vcg/complex/algorithms/inertia.h index d3449fc3..14d92b2a 100644 --- a/vcg/complex/algorithms/inertia.h +++ b/vcg/complex/algorithms/inertia.h @@ -91,7 +91,7 @@ public: Inertia(MeshType &m) {Compute(m);} /* compute various integrations over projection of face */ - void compProjectionIntegrals(FaceType &f) + void compProjectionIntegrals(const FaceType &f) { double a0, a1, da; double b0, b1, db; @@ -148,7 +148,7 @@ public: } -void CompFaceIntegrals(FaceType &f) +void CompFaceIntegrals(const FaceType &f) { Point3 n; ScalarType w; @@ -196,9 +196,8 @@ void Compute(MeshType &m) T0 = T1[X] = T1[Y] = T1[Z] = T2[X] = T2[Y] = T2[Z] = TP[X] = TP[Y] = TP[Z] = 0; - FaceIterator fi; - for (fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD() && vcg::DoubleArea(*fi)>std::numeric_limits::min()) { - FaceType &f=(*fi); + for (auto fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD() && vcg::DoubleArea(*fi)>std::numeric_limits::min()) { + const FaceType &f=(*fi); nx = fabs(f.N()[0]); ny = fabs(f.N()[1]); diff --git a/vcg/complex/algorithms/stat.h b/vcg/complex/algorithms/stat.h index 3ba9db9b..fb2f18b5 100644 --- a/vcg/complex/algorithms/stat.h +++ b/vcg/complex/algorithms/stat.h @@ -192,28 +192,27 @@ public: \short compute the pointcloud barycenter. E.g. it assume each vertex has a mass. If useQualityAsWeight is true, vertex quality is the mass of the vertices */ - static Point3 ComputeCloudBarycenter(MeshType & m, bool useQualityAsWeight=false) - { - if (useQualityAsWeight) - tri::RequirePerVertexQuality(m); - - Point3 barycenter(0, 0, 0); - Point3d accumulator(0.0, 0.0, 0.0); - double weightSum = 0; - VertexIterator vi; - for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if (!(*vi).IsD()) - { - ScalarType weight = useQualityAsWeight ? (*vi).Q() : 1.0f; - accumulator[0] += (double)((*vi).P()[0] * weight); - accumulator[1] += (double)((*vi).P()[1] * weight); - accumulator[2] += (double)((*vi).P()[2] * weight); - weightSum += weight; - } - barycenter[0] = (ScalarType)(accumulator[0] / weightSum); - barycenter[1] = (ScalarType)(accumulator[1] / weightSum); - barycenter[2] = (ScalarType)(accumulator[2] / weightSum); - return barycenter; + static Point3 ComputeCloudBarycenter(const MeshType & m, bool useQualityAsWeight=false) + { + if (useQualityAsWeight) + tri::RequirePerVertexQuality(m); + + Point3 barycenter(0, 0, 0); + Point3d accumulator(0.0, 0.0, 0.0); + double weightSum = 0; + for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi) { + if (!(*vi).IsD()) { + ScalarType weight = useQualityAsWeight ? (*vi).Q() : 1.0f; + accumulator[0] += (double)((*vi).P()[0] * weight); + accumulator[1] += (double)((*vi).P()[1] * weight); + accumulator[2] += (double)((*vi).P()[2] * weight); + weightSum += weight; + } + } + barycenter[0] = (ScalarType)(accumulator[0] / weightSum); + barycenter[1] = (ScalarType)(accumulator[1] / weightSum); + barycenter[2] = (ScalarType)(accumulator[2] / weightSum); + return barycenter; } /** @@ -248,17 +247,17 @@ public: return V; } - static ScalarType ComputeMeshVolume(MeshType & m) + static ScalarType ComputeMeshVolume(const MeshType & m) { Inertia I(m); return I.Mass(); } - static ScalarType ComputeMeshArea(MeshType & m) + static ScalarType ComputeMeshArea(const MeshType & m) { ScalarType area=0; - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for(auto fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) area += DoubleArea(*fi); diff --git a/vcg/simplex/face/component.h b/vcg/simplex/face/component.h index da731066..8134eac6 100644 --- a/vcg/simplex/face/component.h +++ b/vcg/simplex/face/component.h @@ -174,6 +174,7 @@ public: typedef typename T::VertexType::ScalarType ScalarType; inline typename T::VertexType * &V( const int j ) { assert(j>=0 && j<3); return v[j]; } /// \brief The pointer to the i-th vertex + inline const typename T::VertexType * V (const int j) const { assert(j>=0 && j<3); return v[j]; } inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && j<3); return v[j]; } inline CoordType &P( const int j ) { assert(j>=0 && j<3); return v[j]->P(); } /// \brief Shortcut: the position of the i-th vertex (equivalent to \c V(i)->P() ) @@ -182,6 +183,9 @@ public: inline typename T::VertexType * & V0( const int j ) { return V(j);} /** \brief Return the pointer to the j-th vertex of the face. */ inline typename T::VertexType * & V1( const int j ) { return V((j+1)%3);} /** \brief Return the pointer to the ((j+1)%3)-th vertex of the face. */ inline typename T::VertexType * & V2( const int j ) { return V((j+2)%3);} /** \brief Return the pointer to the ((j+2)%3)-th vertex of the face. */ + inline const typename T::VertexType * V0( const int j ) const { return V(j);} /** \brief Return the pointer to the j-th vertex of the face. */ + inline const typename T::VertexType * V1( const int j ) const { return V((j+1)%3);} /** \brief Return the pointer to the ((j+1)%3)-th vertex of the face. */ + inline const typename T::VertexType * V2( const int j ) const { return V((j+2)%3);} /** \brief Return the pointer to the ((j+2)%3)-th vertex of the face. */ inline typename T::VertexType * cV0( const int j ) const { return cV(j);} inline typename T::VertexType * cV1( const int j ) const { return cV((j+1)%3);} inline typename T::VertexType * cV2( const int j ) const { return cV((j+2)%3);} @@ -214,6 +218,7 @@ template class NormalAbs: public T { public: typedef A NormalType; inline NormalType &N() { return _norm; } + inline const NormalType &N() const { return _norm; } inline NormalType cN() const { return _norm; } template void ImportData(const RightValueType & rightF) From abb29e730026783b72869be6330826da5f6c8376 Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 8 Feb 2021 23:03:37 +0100 Subject: [PATCH 059/140] Close opened files when reading an STL file. --- wrap/io_trimesh/import_stl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wrap/io_trimesh/import_stl.h b/wrap/io_trimesh/import_stl.h index 90510e9d..31c9739f 100644 --- a/wrap/io_trimesh/import_stl.h +++ b/wrap/io_trimesh/import_stl.h @@ -140,6 +140,7 @@ static bool IsSTLColored(const char * filename, bool &coloredFlag, bool &magicsM } } + fclose(fp); return true; } @@ -163,6 +164,7 @@ static bool IsSTLBinary(const char * filename, bool &binaryFlag) if(file_size == expected_file_size) { binaryFlag = true; + fclose(fp); return true; } From 4ae9537e75c4535d98a61175e38a2f8667c2a65b Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Wed, 10 Feb 2021 12:33:03 +0100 Subject: [PATCH 060/140] added check for file path length when opening a mesh with the generic importer --- wrap/io_trimesh/import.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/wrap/io_trimesh/import.h b/wrap/io_trimesh/import.h index 96d161bb..0961f3d8 100644 --- a/wrap/io_trimesh/import.h +++ b/wrap/io_trimesh/import.h @@ -115,7 +115,12 @@ static int Open(OpenMeshType &m, const char *filename, CallBackPos *cb=0) static int Open(OpenMeshType &m, const char *filename, int &loadmask, CallBackPos *cb=0) { int err; - if(FileExtension(filename,"ply")) + if (strlen(filename) < 3) + { + err = -1; + LastType()=KT_UNKNOWN; + } + else if(FileExtension(filename,"ply")) { err = ImporterPLY::Open(m, filename, loadmask, cb); LastType()=KT_PLY; @@ -140,7 +145,7 @@ static int Open(OpenMeshType &m, const char *filename, int &loadmask, CallBackPo err = ImporterVMI::Open(m, filename, loadmask, cb); LastType()=KT_VMI; } - else { + else { err=1; LastType()=KT_UNKNOWN; } @@ -152,7 +157,7 @@ static bool ErrorCritical(int error) { switch(LastType()) { - case KT_PLY : return (error>0); break; + case KT_PLY : return ImporterPLY::ErrorCritical(error); break; case KT_STL : return (error>0); break; case KT_OFF : return (error>0); break; case KT_OBJ : return ImporterOBJ::ErrorCritical(error); break; From e292f0cc9ba2c6516f958f88bccd6437c2d92320 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 12 Feb 2021 17:48:34 +0100 Subject: [PATCH 061/140] fix malformed file on some stl files (see https://github.com/cnr-isti-vclab/meshlab/issues/732) --- wrap/io_trimesh/import_stl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/io_trimesh/import_stl.h b/wrap/io_trimesh/import_stl.h index 11eb57c3..2a202098 100644 --- a/wrap/io_trimesh/import_stl.h +++ b/wrap/io_trimesh/import_stl.h @@ -150,7 +150,7 @@ static bool IsSTLColored(const char * filename, bool &coloredFlag, bool &magicsM static bool IsSTLBinary(const char * filename, bool &binaryFlag) { binaryFlag=false; - FILE *fp = fopen(filename, "r"); + FILE *fp = fopen(filename, "rb"); /* Find size of file */ fseek(fp, 0, SEEK_END); long file_size = ftell(fp); From fed787ebb9ffc6cc35eb53af1d06980618eecca6 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 2 Mar 2021 14:25:30 +0100 Subject: [PATCH 062/140] fix stl filesize computation for >2gb files (see https://github.com/cnr-isti-vclab/meshlab/issues/924) --- wrap/io_trimesh/import_stl.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/wrap/io_trimesh/import_stl.h b/wrap/io_trimesh/import_stl.h index 2a202098..106067ee 100644 --- a/wrap/io_trimesh/import_stl.h +++ b/wrap/io_trimesh/import_stl.h @@ -24,7 +24,7 @@ #ifndef __VCGLIB_IMPORT_STL #define __VCGLIB_IMPORT_STL #include -#include +#include #include namespace vcg { @@ -153,13 +153,13 @@ static bool IsSTLBinary(const char * filename, bool &binaryFlag) FILE *fp = fopen(filename, "rb"); /* Find size of file */ fseek(fp, 0, SEEK_END); - long file_size = ftell(fp); + unsigned long file_size = ftell(fp); unsigned int facenum; /* Check for binary or ASCII file */ fseek(fp, STL_LABEL_SIZE, SEEK_SET); fread(&facenum, sizeof(unsigned int), 1, fp); - long expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; + unsigned long expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; if(file_size == expected_file_size) { binaryFlag = true; @@ -169,15 +169,16 @@ static bool IsSTLBinary(const char * filename, bool &binaryFlag) // second check, sometimes the size is a bit wrong, // lets'make a test to check that we find only ascii stuff before assuming it is ascii unsigned char tmpbuf[1000]; - int byte_to_read = std::min(int(sizeof(tmpbuf)), int(file_size - 80)); + unsigned long byte_to_read = std::min(sizeof(tmpbuf), file_size - 80); fread(tmpbuf, byte_to_read,1,fp); fclose(fp); - for(int i = 0; i < byte_to_read; i++) + for(unsigned long i = 0; i < byte_to_read; i++) { if(tmpbuf[i] > 127) { binaryFlag=true; - if(abs(file_size-expected_file_size) > file_size/20 ) + unsigned long diff = (file_size > expected_file_size) ? file_size-expected_file_size : expected_file_size-file_size; + if(diff > file_size/20 ) return false; // break; } From a7c1893b8d646116f19ce3c9fcbf2c4a294cfe9d Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 2 Mar 2021 15:16:02 +0100 Subject: [PATCH 063/140] fix export collada also with double precision scalars --- wrap/dae/colladaformat.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wrap/dae/colladaformat.h b/wrap/dae/colladaformat.h index 29b6dfe7..3b6c6f8e 100644 --- a/wrap/dae/colladaformat.h +++ b/wrap/dae/colladaformat.h @@ -38,9 +38,9 @@ template struct CoordNumber{public: static unsigned int coord() { return 0; }}; -template<> struct CoordNumber { public: static unsigned int coord() { return 2; } }; -template<> struct CoordNumber { public: static unsigned int coord() { return 3; } }; -template<> struct CoordNumber { public: static unsigned int coord() { return 4; } }; +template struct CoordNumber> { public: static unsigned int coord() { return 2; } }; +template struct CoordNumber> { public: static unsigned int coord() { return 3; } }; +template struct CoordNumber> { public: static unsigned int coord() { return 4; } }; template<> struct CoordNumber { public: static unsigned int coord() { return 4; } }; From b54ca75043c5ddb06f7eda756b9299137b89f080 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 2 Mar 2021 15:32:35 +0100 Subject: [PATCH 064/140] fix import_stl for windows build --- wrap/io_trimesh/import_stl.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wrap/io_trimesh/import_stl.h b/wrap/io_trimesh/import_stl.h index 106067ee..16517399 100644 --- a/wrap/io_trimesh/import_stl.h +++ b/wrap/io_trimesh/import_stl.h @@ -153,13 +153,13 @@ static bool IsSTLBinary(const char * filename, bool &binaryFlag) FILE *fp = fopen(filename, "rb"); /* Find size of file */ fseek(fp, 0, SEEK_END); - unsigned long file_size = ftell(fp); + std::size_t file_size = ftell(fp); unsigned int facenum; /* Check for binary or ASCII file */ fseek(fp, STL_LABEL_SIZE, SEEK_SET); fread(&facenum, sizeof(unsigned int), 1, fp); - unsigned long expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; + std::size_t expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; if(file_size == expected_file_size) { binaryFlag = true; @@ -169,15 +169,15 @@ static bool IsSTLBinary(const char * filename, bool &binaryFlag) // second check, sometimes the size is a bit wrong, // lets'make a test to check that we find only ascii stuff before assuming it is ascii unsigned char tmpbuf[1000]; - unsigned long byte_to_read = std::min(sizeof(tmpbuf), file_size - 80); + std::size_t byte_to_read = std::min(sizeof(tmpbuf), (size_t)file_size - 80); fread(tmpbuf, byte_to_read,1,fp); fclose(fp); - for(unsigned long i = 0; i < byte_to_read; i++) + for(std::size_t i = 0; i < byte_to_read; i++) { if(tmpbuf[i] > 127) { binaryFlag=true; - unsigned long diff = (file_size > expected_file_size) ? file_size-expected_file_size : expected_file_size-file_size; + std::size_t diff = (file_size > expected_file_size) ? file_size-expected_file_size : expected_file_size-file_size; if(diff > file_size/20 ) return false; // break; From 7a62fd2c7a15046e10927eee7d1825ba6a71f6c8 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 5 Mar 2021 12:30:23 +0100 Subject: [PATCH 065/140] fixed return type nonsense --- vcg/simplex/face/component_polygon.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index 8ac67f47..b17c2f85 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -67,23 +67,23 @@ public: */ // ~PFVAdj(){ __Dealloc(); } - inline typename T::VertexType * & V( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]; } - inline typename T::VertexType * const & V( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } - inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } + inline typename T::VertexType * & V( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]; } + inline typename T::VertexType * V( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } + inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @param j Index of the face vertex. */ - inline VertexType * & V0( const int j ) { return V(j);} - inline VertexType * & V1( const int j ) { return V((j+1)%this->VN());} - inline VertexType * & V2( const int j ) { return V((j+2)%this->VN());} - inline const VertexType * const & V0( const int j ) const { return V(j);} - inline const VertexType * const & V1( const int j ) const { return V((j+1)%this->VN());} - inline const VertexType * const & V2( const int j ) const { return V((j+2)%this->VN());} - inline const VertexType * const & cV0( const int j ) const { return cV(j);} - inline const VertexType * const & cV1( const int j ) const { return cV((j+1)%this->VN());} - inline const VertexType * const & cV2( const int j ) const { return cV((j+2)%this->VN());} + inline VertexType * & V0( const int j ) { return V(j);} + inline VertexType * & V1( const int j ) { return V((j+1)%this->VN());} + inline VertexType * & V2( const int j ) { return V((j+2)%this->VN());} + inline const VertexType * V0( const int j ) const { return V(j);} + inline const VertexType * V1( const int j ) const { return V((j+1)%this->VN());} + inline const VertexType * V2( const int j ) const { return V((j+2)%this->VN());} + inline const VertexType * cV0( const int j ) const { return cV(j);} + inline const VertexType * cV1( const int j ) const { return cV((j+1)%this->VN());} + inline const VertexType * cV2( const int j ) const { return cV((j+2)%this->VN());} inline CoordType &P( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]->P(); } inline CoordType cP( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]->cP(); } From 3ef68d60091d0c845f51110773662c97e0cd9116 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 5 Mar 2021 12:54:13 +0100 Subject: [PATCH 066/140] missing include --- wrap/nanoply/include/nanoply.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wrap/nanoply/include/nanoply.hpp b/wrap/nanoply/include/nanoply.hpp index d35473a6..5a213560 100644 --- a/wrap/nanoply/include/nanoply.hpp +++ b/wrap/nanoply/include/nanoply.hpp @@ -30,6 +30,7 @@ #include #include #include +#include // Avoid conflicting declaration of min/max macros in windows headers From 399ebd99ca2fdecb05bfbe0f14bfa29ddb6c3af6 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Tue, 9 Mar 2021 22:51:32 +0100 Subject: [PATCH 067/140] const --- vcg/complex/algorithms/parametrization/uv_utils.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vcg/complex/algorithms/parametrization/uv_utils.h b/vcg/complex/algorithms/parametrization/uv_utils.h index 6318310e..e93bcedf 100644 --- a/vcg/complex/algorithms/parametrization/uv_utils.h +++ b/vcg/complex/algorithms/parametrization/uv_utils.h @@ -96,11 +96,10 @@ public: } ///calculate the BBox in UV space - static vcg::Box2 PerVertUVBox(MeshType &m) + static vcg::Box2 PerVertUVBox(const MeshType &m) { vcg::Box2 UVBox; - VertexIterator vi; - for (vi=m.vert.begin();vi!=m.vert.end();vi++) + for (auto vi=m.vert.begin();vi!=m.vert.end();vi++) { if ((*vi).IsD()) continue; UVBox.Add((*vi).T().P()); From bff978189b6eeb0f22efdcfa479048e7403efbfb Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 11 Mar 2021 16:04:35 +0100 Subject: [PATCH 068/140] switch to std::shuffle in point_sampling (std::random_shuffle deprecated) --- vcg/complex/algorithms/point_sampling.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index 10047237..0afbb3ba 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -713,7 +713,7 @@ static void FillAndShuffleFacePointerVector(MeshType & m, std::vector &vertVec) { @@ -723,7 +723,7 @@ static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector Date: Thu, 11 Mar 2021 18:57:18 +0100 Subject: [PATCH 069/140] using urbg generator for std::shuffle --- vcg/complex/algorithms/point_sampling.h | 28 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index 0afbb3ba..1d61bbfd 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -494,6 +494,18 @@ static math::MarsenneTwisterRNG &SamplingRandomGenerator() return rnd; } +class MarsenneTwisterURBG +{ +public: + MarsenneTwisterURBG(unsigned int max) : _max(max) {} + typedef unsigned int result_type; + unsigned int min() const {return 0;} + unsigned int max() const {return _max;} + unsigned int operator()() {return RandomInt(_max);} +private: + unsigned int _max; +}; + // Returns an integer random number in the [0,i-1] interval using the improve Marsenne-Twister method. // this functor is needed for passing it to the std functions. static unsigned int RandomInt(unsigned int i) @@ -712,8 +724,8 @@ static void FillAndShuffleFacePointerVector(MeshType & m, std::vector &vertVec) { @@ -722,8 +734,8 @@ static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector Date: Thu, 11 Mar 2021 19:21:56 +0100 Subject: [PATCH 070/140] fixes due to min/max... --- .../trimesh_sampling/trimesh_sampling.pro | 5 +++ vcg/complex/algorithms/point_sampling.h | 32 +++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/sample/trimesh_sampling/trimesh_sampling.pro b/apps/sample/trimesh_sampling/trimesh_sampling.pro index e112f066..1f9039f4 100644 --- a/apps/sample/trimesh_sampling/trimesh_sampling.pro +++ b/apps/sample/trimesh_sampling/trimesh_sampling.pro @@ -1,3 +1,8 @@ include(../common.pri) TARGET = trimesh_sampling SOURCES += trimesh_sampling.cpp + +# Awful.. +win32{ + DEFINES += NOMINMAX +} diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index 1d61bbfd..8e2418ed 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -494,18 +494,6 @@ static math::MarsenneTwisterRNG &SamplingRandomGenerator() return rnd; } -class MarsenneTwisterURBG -{ -public: - MarsenneTwisterURBG(unsigned int max) : _max(max) {} - typedef unsigned int result_type; - unsigned int min() const {return 0;} - unsigned int max() const {return _max;} - unsigned int operator()() {return RandomInt(_max);} -private: - unsigned int _max; -}; - // Returns an integer random number in the [0,i-1] interval using the improve Marsenne-Twister method. // this functor is needed for passing it to the std functions. static unsigned int RandomInt(unsigned int i) @@ -513,6 +501,18 @@ static unsigned int RandomInt(unsigned int i) return (SamplingRandomGenerator().generate(i)); } +class MarsenneTwisterURBG +{ +public: + typedef unsigned int result_type; + MarsenneTwisterURBG(result_type max) : _max(max) {} + result_type min() const {return 0;} + result_type max() const {return _max;} + result_type operator()() {return SamplingRandomGenerator().generate(_max);} +private: + result_type _max; +}; + // Returns a random number in the [0,1) real interval using the improved Marsenne-Twister method. static double RandomDouble01() { @@ -725,7 +725,7 @@ static void FillAndShuffleFacePointerVector(MeshType & m, std::vector &vertVec) { @@ -735,7 +735,7 @@ static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector Date: Thu, 11 Mar 2021 19:42:30 +0100 Subject: [PATCH 071/140] using std::mt19937 --- vcg/complex/algorithms/point_sampling.h | 33 +++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index 8e2418ed..702dbdef 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -35,6 +35,7 @@ sampling strategies (montecarlo, stratified etc). #ifndef __VCGLIB_POINT_SAMPLING #define __VCGLIB_POINT_SAMPLING +#include #include #include @@ -501,18 +502,6 @@ static unsigned int RandomInt(unsigned int i) return (SamplingRandomGenerator().generate(i)); } -class MarsenneTwisterURBG -{ -public: - typedef unsigned int result_type; - MarsenneTwisterURBG(result_type max) : _max(max) {} - result_type min() const {return 0;} - result_type max() const {return _max;} - result_type operator()() {return SamplingRandomGenerator().generate(_max);} -private: - result_type _max; -}; - // Returns a random number in the [0,1) real interval using the improved Marsenne-Twister method. static double RandomDouble01() { @@ -725,7 +714,9 @@ static void FillAndShuffleFacePointerVector(MeshType & m, std::vector &vertVec) { @@ -735,7 +726,9 @@ static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector Date: Thu, 18 Mar 2021 17:17:09 +0100 Subject: [PATCH 072/140] face const correctness --- vcg/simplex/face/component.h | 89 ++++++++++++++++++++++++-------- vcg/simplex/face/component_ocf.h | 66 +++++++++++++++++++---- 2 files changed, 123 insertions(+), 32 deletions(-) diff --git a/vcg/simplex/face/component.h b/vcg/simplex/face/component.h index 8134eac6..2fda0b9d 100644 --- a/vcg/simplex/face/component.h +++ b/vcg/simplex/face/component.h @@ -37,10 +37,13 @@ namespace face { template class EmptyCore: public T { public: inline typename T::VertexType * &V( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } + inline typename T::VertexType * V( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * cV( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * &FVp( const int i ) { return this->V(i); } + inline typename T::VertexType * FVp( const int i ) const { return this->cV(i); } inline typename T::VertexType * cFVp( const int i ) const { return this->cV(i); } inline typename T::CoordType &P( const int ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } + inline typename T::CoordType P( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline typename T::CoordType cP( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } static bool HasVertexRef() { return false; } @@ -49,23 +52,28 @@ public: typedef typename T::VertexType::NormalType NormalType; typedef NormalType WedgeNormalType; NormalType &N() { static NormalType dummy_normal(0, 0, 0); assert(0); return dummy_normal; } - NormalType cN() const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } + const NormalType& N() const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } + const NormalType& cN() const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } WedgeNormalType &WN(int) { static NormalType dummy_normal(0, 0, 0); assert(0); return dummy_normal; } - WedgeNormalType cWN(int) const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } + const WedgeNormalType& WN(int) const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } + const WedgeNormalType& cWN(int) const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } typedef int WedgeTexCoordType; typedef vcg::TexCoord2 TexCoordType; TexCoordType &WT(const int) { static TexCoordType dummy_texture; assert(0); return dummy_texture;} - TexCoordType const &cWT(const int) const { static TexCoordType dummy_texture; return dummy_texture;} + const TexCoordType & WT(const int) const { static TexCoordType dummy_texture; return dummy_texture;} + const TexCoordType &cWT(const int) const { static TexCoordType dummy_texture; return dummy_texture;} typedef int FlagType; int &Flags() { static int dummyflags(0); assert(0); return dummyflags; } + int Flags() const { return 0; } int cFlags() const { return 0; } static bool HasFlags() { return false; } inline void InitIMark() { } inline int &IMark() { assert(0); static int tmp=-1; return tmp;} + inline int IMark() const { return 0;} inline int cIMark() const { return 0;} typedef int MarkType; @@ -74,13 +82,17 @@ public: typedef vcg::Color4b ColorType; typedef ColorType WedgeColorType; ColorType &C() { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } - ColorType cC() const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } + const ColorType& C() const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } + const ColorType& cC() const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } WedgeColorType &WC(const int) { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } - WedgeColorType cWC(const int) const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } + const WedgeColorType& WC(const int) const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } + const WedgeColorType& cWC(const int) const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } QualityType &Q() { static QualityType dummyQuality(0); assert(0); return dummyQuality; } - QualityType cQ() const { static QualityType dummyQuality(0); assert(0); return dummyQuality; } + const QualityType& Q() const { static QualityType dummyQuality(0); assert(0); return dummyQuality; } + const QualityType& cQ() const { static QualityType dummyQuality(0); assert(0); return dummyQuality; } Quality3Type &Q3() { static Quality3Type dummyQuality3(0,0,0); assert(0); return dummyQuality3; } - Quality3Type cQ3() const { static Quality3Type dummyQuality3(0,0,0); assert(0); return dummyQuality3; } + const Quality3Type& Q3() const { static Quality3Type dummyQuality3(0,0,0); assert(0); return dummyQuality3; } + const Quality3Type& cQ3() const { static Quality3Type dummyQuality3(0,0,0); assert(0); return dummyQuality3; } static bool HasColor() { return false; } static bool HasQuality() { return false; } @@ -106,17 +118,22 @@ public: typedef int VFAdjType; typename T::FacePointer &VFp(int) { static typename T::FacePointer fp=0; assert(0); return fp; } + typename T::FacePointer VFp(int) const { static typename T::FacePointer fp=0; assert(0); return fp; } typename T::FacePointer cVFp(int) const { static typename T::FacePointer fp=0; assert(0); return fp; } typename T::FacePointer &FFp(int) { static typename T::FacePointer fp=0; assert(0); return fp; } + typename T::FacePointer FFp(int) const { static typename T::FacePointer fp=0; assert(0); return fp; } typename T::FacePointer cFFp(int) const { static typename T::FacePointer fp=0; assert(0); return fp; } typename T::EdgePointer &FEp(int) { static typename T::EdgePointer fp=0; assert(0); return fp; } + typename T::EdgePointer FEp(int) const { static typename T::EdgePointer fp=0; assert(0); return fp; } typename T::EdgePointer cFEp(int) const { static typename T::EdgePointer fp=0; assert(0); return fp; } typename T::HEdgePointer &FHp() { static typename T::HEdgePointer fp=0; assert(0); return fp; } + typename T::HEdgePointer FHp() const { static typename T::HEdgePointer fp=0; assert(0); return fp; } typename T::HEdgePointer cFHp() const { static typename T::HEdgePointer fp=0; assert(0); return fp; } char &VFi(int) { static char z=0; assert(0); return z;} char VFi(int) const { static char z=0; assert(0); return z;} - char &FFi(int) { static char z=0; assert(0); return z;} char cVFi(int) const { static char z=0; assert(0); return z;} + char &FFi(int) { static char z=0; assert(0); return z;} + char FFi(int) const { static char z=0; assert(0); return z;} char cFFi(int) const { static char z=0; assert(0); return z;} bool IsVFInitialized(const int j) const {return static_cast(this)->cVFi(j)!=-1;} void VFClear(int j) { @@ -135,13 +152,17 @@ public: typedef typename T::ScalarType CurScalarType; CurVecType &PD1() { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } CurVecType &PD2() { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } - CurVecType cPD1() const { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } - CurVecType cPD2() const { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } + const CurVecType& PD1() const { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } + const CurVecType& PD2() const { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } + const CurVecType& cPD1() const { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } + const CurVecType& cPD2() const { static typename T::CoordType dummy(0, 0, 0); assert(0); return dummy; } CurScalarType &K1() { static typename T::ScalarType dummy(0); assert(0); return dummy; } CurScalarType &K2() { static typename T::ScalarType dummy(0); assert(0); return dummy; } - CurScalarType cK1() const { static typename T::ScalarType dummy(0); assert(0); return dummy; } - CurScalarType cK2() const { static typename T::ScalarType dummy(0); assert(0); return dummy; } + const CurScalarType& K1() const { static typename T::ScalarType dummy(0); assert(0); return dummy; } + const CurScalarType& K2() const { static typename T::ScalarType dummy(0); assert(0); return dummy; } + const CurScalarType& cK1() const { static typename T::ScalarType dummy(0); assert(0); return dummy; } + const CurScalarType& cK2() const { static typename T::ScalarType dummy(0); assert(0); return dummy; } static bool HasCurvatureDir() { return false; } @@ -177,8 +198,9 @@ public: inline const typename T::VertexType * V (const int j) const { assert(j>=0 && j<3); return v[j]; } inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && j<3); return v[j]; } - inline CoordType &P( const int j ) { assert(j>=0 && j<3); return v[j]->P(); } /// \brief Shortcut: the position of the i-th vertex (equivalent to \c V(i)->P() ) - inline CoordType cP( const int j ) const { assert(j>=0 && j<3); return v[j]->cP(); } + inline CoordType &P( const int j ) { assert(j>=0 && j<3); return v[j]->P(); } /// \brief Shortcut: the position of the i-th vertex (equivalent to \c V(i)->P() ) + inline const CoordType &P( const int j ) const { assert(j>=0 && j<3); return v[j]->P(); } + inline CoordType cP( const int j ) const { assert(j>=0 && j<3); return v[j]->cP(); } inline typename T::VertexType * & V0( const int j ) { return V(j);} /** \brief Return the pointer to the j-th vertex of the face. */ inline typename T::VertexType * & V1( const int j ) { return V((j+1)%3);} /** \brief Return the pointer to the ((j+1)%3)-th vertex of the face. */ @@ -193,6 +215,9 @@ public: inline CoordType & P0( const int j ) { return V(j)->P();} inline CoordType & P1( const int j ) { return V((j+1)%3)->P();} inline CoordType & P2( const int j ) { return V((j+2)%3)->P();} + inline const CoordType & P0( const int j ) const { return V(j)->P();} + inline const CoordType & P1( const int j ) const { return V((j+1)%3)->P();} + inline const CoordType & P2( const int j ) const { return V((j+2)%3)->P();} inline const CoordType & cP0( const int j ) const { return cV(j)->P();} inline const CoordType & cP1( const int j ) const { return cV((j+1)%3)->P();} inline const CoordType & cP2( const int j ) const { return cV((j+2)%3)->P();} @@ -240,7 +265,8 @@ template class WedgeNormal: public T { public: typedef typename T::VertexType::NormalType WedgeNormalType; inline WedgeNormalType &WN(int j) { return _wnorm[j]; } - inline WedgeNormalType cWN(int j) const { return _wnorm[j]; } + inline const WedgeNormalType& WN(int j) const { return _wnorm[j]; } + inline const WedgeNormalType& cWN(int j) const { return _wnorm[j]; } template void ImportData(const RightValueType & rightF){ if(rightF.IsWedgeNormalEnabled()) for (int i=0; i<3; ++i) { WN(i) = rightF.cWN(i); } T::ImportData(rightF);} inline void Alloc(const int & ns){T::Alloc(ns);} @@ -256,7 +282,8 @@ template class WedgeRealNormal: public T { public: typedef A WedgeNormalType; inline WedgeNormalType &WN(int i) { return _wn[i]; } - inline WedgeNormalType cWN(int i) const { return _wn[i]; } + inline const WedgeNormalType& WN(int i) const { return _wn[i]; } + inline const WedgeNormalType& cWN(int i) const { return _wn[i]; } template void ImportData(const RightValueType & rightF){ if(RightValueType::HasWedgeNormal()) for (int i=0; i<3; ++i) { WN(i) = rightF.cWN(i); } T::ImportData(rightF);} inline void Alloc(const int & ns){T::Alloc(ns);} @@ -293,7 +320,8 @@ public: typedef int WedgeTexCoordType; typedef A TexCoordType; TexCoordType &WT(const int i) { return _wt[i]; } - TexCoordType cWT(const int i) const { return _wt[i]; } + const TexCoordType& WT(const int i) const { return _wt[i]; } + const TexCoordType& cWT(const int i) const { return _wt[i]; } template void ImportData(const RightValueType & rightF){ if(rightF.IsWedgeTexCoordEnabled()) @@ -329,6 +357,7 @@ public: BitFlags():_flags(0) {} typedef int FlagType; int &Flags() {return _flags; } + int Flags() const {return _flags; } int cFlags() const {return _flags; } template void ImportData(const RightValueType & rightF){ @@ -351,7 +380,8 @@ public: typedef A ColorType; Color():_color(vcg::Color4b::White) {} ColorType &C() { return _color; } - ColorType cC() const { return _color; } + const ColorType& C() const { return _color; } + const ColorType& cC() const { return _color; } template void ImportData(const RightValueType & rightF){ if(rightF.IsColorEnabled()) C() = rightF.cC(); @@ -370,7 +400,8 @@ template class WedgeColor: public T { public: typedef A WedgeColorType; WedgeColorType &WC(int i) { return _color[i]; } - WedgeColorType cWC(int i) const { return _color[i]; } + const WedgeColorType& WC(int i) const { return _color[i]; } + const WedgeColorType& cWC(int i) const { return _color[i]; } template void ImportData(const RightValueType & rightF){ @@ -404,7 +435,8 @@ public: typedef A QualityType; Quality():_quality(0) {} QualityType &Q() { return _quality; } - QualityType cQ() const { return _quality; } + const QualityType& Q() const { return _quality; } + const QualityType& cQ() const { return _quality; } template void ImportData(const RightValueType & rightF){ if(rightF.IsQualityEnabled()) @@ -434,7 +466,8 @@ template class Quality3: public T { public: typedef vcg::Point3 Quality3Type; Quality3Type &Q3() { return _quality; } - Quality3Type cQ3() const { return _quality; } + const Quality3Type& Q3() const { return _quality; } + const Quality3Type& cQ3() const { return _quality; } template void ImportData(const RightValueType & rightF){ if(rightF.IsQuality3Enabled()) Q3() = rightF.cQ3(); @@ -468,6 +501,7 @@ template class Mark: public T { public: Mark():_imark(0){} inline int &IMark() { return _imark;} + inline int IMark() const { return _imark;} inline int cIMark() const { return _imark;} inline void InitIMark() { _imark = 0; } static bool HasMark() { return true; } @@ -501,11 +535,15 @@ public: CurVecType &PD1() { return _curv.max_dir;} CurVecType &PD2() { return _curv.min_dir;} + const CurVecType &PD1() const { return _curv.max_dir;} + const CurVecType &PD2() const { return _curv.min_dir;} CurVecType cPD1() const { return _curv.max_dir;} CurVecType cPD2() const { return _curv.min_dir;} CurScalarType &K1() { return _curv.k1;} CurScalarType &K2() { return _curv.k2;} + const CurScalarType &K1() const { return _curv.k1;} + const CurScalarType &K2() const { return _curv.k2;} CurScalarType cK1() const {return _curv.k1;} CurScalarType cK2() const {return _curv.k2;} template < class RightValueType> @@ -560,8 +598,10 @@ public: _vfi[2]=-1; } typename T::FacePointer &VFp(const int j) { assert(j>=0 && j<3); return _vfp[j]; } + typename T::FacePointer VFp(const int j) const { assert(j>=0 && j<3); return _vfp[j]; } typename T::FacePointer cVFp(const int j) const { assert(j>=0 && j<3); return _vfp[j]; } char &VFi(const int j) {return _vfi[j]; } + char VFi(const int j)const {return _vfi[j]; } char cVFi(const int j)const {return _vfi[j]; } template void ImportData(const RightValueType & rightF){T::ImportData(rightF);} @@ -589,6 +629,7 @@ public: typename T::FacePointer &EFp(const int j) { assert(j>=0 && j<3); return _efp[j]; } typename T::FacePointer cEFp(const int j) const { assert(j>=0 && j<3); return _efp[j]; } char &VFi(const int j) {return _efi[j]; } + char VFi(const int j) const {return _efi[j]; } template void ImportData(const RightValueType & rightF){T::ImportData(rightF);} inline void Alloc(const int & ns){T::Alloc(ns);} @@ -624,12 +665,16 @@ public: _ffp[2]=nullptr; } typename T::FacePointer &FFp(const int j) { assert(j>=0 && j<3); return _ffp[j]; } + typename T::FacePointer FFp(const int j) const { assert(j>=0 && j<3); return _ffp[j]; } typename T::FacePointer cFFp(const int j) const { assert(j>=0 && j<3); return _ffp[j]; } char &FFi(const int j) { return _ffi[j]; } + char FFi(const int j) const { return _ffi[j]; } char cFFi(const int j) const { return _ffi[j]; } typename T::FacePointer &FFp1( const int j ) { return FFp((j+1)%3);} typename T::FacePointer &FFp2( const int j ) { return FFp((j+2)%3);} + typename T::FacePointer FFp1( const int j ) const { return FFp((j+1)%3);} + typename T::FacePointer FFp2( const int j ) const { return FFp((j+2)%3);} typename T::FacePointer cFFp1( const int j ) const { return FFp((j+1)%3);} typename T::FacePointer cFFp2( const int j ) const { return FFp((j+2)%3);} @@ -657,6 +702,7 @@ public: } typename T::EdgePointer &FEp( int j) { assert(j>=0 && j<3); return _fep[j]; } + typename T::EdgePointer FEp( int j) const { assert(j>=0 && j<3); return _fep[j]; } typename T::EdgePointer cFEp( int j) const { assert(j>=0 && j<3); return _fep[j]; } typename T::EdgePointer &FEp1( int j ) { return FEp((j+1)%3);} @@ -682,6 +728,7 @@ template class FHAdj: public T { public: FHAdj(){_fh=0;} typename T::HEdgePointer &FHp( ) { return _fh; } + typename T::HEdgePointer FHp( ) const { return _fh; } typename T::HEdgePointer cFHp( ) const { return _fh; } template diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index 2707dc22..3f676006 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -398,6 +398,11 @@ public: return (*this).Base().AV[(*this).Index()]._fp[j]; } + typename T::FacePointer VFp(const int j) const { + if(! (*this).Base().VFAdjacencyEnabled ) return 0; + else return (*this).Base().AV[(*this).Index()]._fp[j]; + } + typename T::FacePointer cVFp(const int j) const { if(! (*this).Base().VFAdjacencyEnabled ) return 0; else return (*this).Base().AV[(*this).Index()]._fp[j]; @@ -436,6 +441,11 @@ public: return (*this).Base().AF[(*this).Index()]._fp[j]; } + typename T::FacePointer FFp(const int j) const { + if(! (*this).Base().FFAdjacencyEnabled ) return 0; + else return (*this).Base().AF[(*this).Index()]._fp[j]; + } + typename T::FacePointer cFFp(const int j) const { if(! (*this).Base().FFAdjacencyEnabled ) return 0; else return (*this).Base().AF[(*this).Index()]._fp[j]; @@ -445,6 +455,12 @@ public: assert((*this).Base().FFAdjacencyEnabled); return (*this).Base().AF[(*this).Index()]._zp[j]; } + + char FFi(const int j) const { + assert((*this).Base().FFAdjacencyEnabled); + return (*this).Base().AF[(*this).Index()]._zp[j]; + } + char cFFi(const int j) const { assert((*this).Base().FFAdjacencyEnabled); return (*this).Base().AF[(*this).Index()]._zp[j]; @@ -452,11 +468,14 @@ public: typename T::FacePointer &FFp1( const int j ) { return FFp((j+1)%3);} typename T::FacePointer &FFp2( const int j ) { return FFp((j+2)%3);} + typename T::FacePointer FFp1( const int j ) const { return FFp((j+1)%3);} + typename T::FacePointer FFp2( const int j ) const { return FFp((j+2)%3);} typename T::FacePointer cFFp1( const int j ) const { return FFp((j+1)%3);} typename T::FacePointer cFFp2( const int j ) const { return FFp((j+2)%3);} typename T::FacePointer &Neigh( const int j ) { return FFp(j);} - typename T::FacePointer cNeigh( const int j ) const { return cFFp(j);} + typename T::FacePointer Neigh( const int j ) const { return FFp(j);} + typename T::FacePointer cNeigh( const int j ) const { return FFp(j);} unsigned int SizeNeigh(){return 3;} template @@ -479,7 +498,13 @@ public: // you cannot use Normals before enabling them with: yourmesh.face.EnableNormal() assert((*this).Base().NormalEnabled); return (*this).Base().NV[(*this).Index()]; } - NormalType cN() const { + + const NormalType& N() const { + // you cannot use Normals before enabling them with: yourmesh.face.EnableNormal() + assert((*this).Base().NormalEnabled); + return (*this).Base().NV[(*this).Index()]; } + + const NormalType& cN() const { // you cannot use Normals before enabling them with: yourmesh.face.EnableNormal() assert((*this).Base().NormalEnabled); return (*this).Base().NV[(*this).Index()]; } @@ -518,13 +543,17 @@ public: CurVecType &PD1() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].max_dir; } CurVecType &PD2() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].min_dir; } - CurVecType cPD1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].max_dir; } - CurVecType cPD2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].min_dir; } + const CurVecType& PD1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].max_dir; } + const CurVecType& PD2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].min_dir; } + const CurVecType& cPD1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].max_dir; } + const CurVecType& cPD2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].min_dir; } CurScalarType &K1() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k1; } CurScalarType &K2() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k2; } - CurScalarType cK1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k1; } - CurScalarType cK2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k2; } + const CurScalarType& K1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k1; } + const CurScalarType& K2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k2; } + const CurScalarType& cK1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k1; } + const CurScalarType& cK2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CDV[(*this).Index()].k2; } template void ImportData(const RightFaceType & rightF){ @@ -554,7 +583,11 @@ public: assert((*this).Base().QualityEnabled); return (*this).Base().QV[(*this).Index()]; } - QualityType cQ() const { + const QualityType& Q() const { + assert((*this).Base().QualityEnabled); + return (*this).Base().QV[(*this).Index()]; + } + const QualityType& cQ() const { assert((*this).Base().QualityEnabled); return (*this).Base().QV[(*this).Index()]; } @@ -580,7 +613,11 @@ public: assert((*this).Base()._ColorEnabled); return (*this).Base().CV[(*this).Index()]; } - ColorType cC() const { + const ColorType& C() const { + assert((*this).Base()._ColorEnabled); + return (*this).Base().CV[(*this).Index()]; + } + const ColorType& cC() const { assert((*this).Base()._ColorEnabled); return (*this).Base().CV[(*this).Index()]; } @@ -605,6 +642,10 @@ public: assert((*this).Base().MarkEnabled); return (*this).Base().MV[(*this).Index()]; } + inline int IMark() const { + assert((*this).Base().MarkEnabled); + return (*this).Base().MV[(*this).Index()]; + } inline int cIMark() const { assert((*this).Base().MarkEnabled); return (*this).Base().MV[(*this).Index()]; @@ -628,7 +669,8 @@ public: WedgeTexCoordOcf(){ } typedef A TexCoordType; TexCoordType &WT(const int i) { assert((*this).Base().WedgeTexEnabled); return (*this).Base().WTV[(*this).Index()].wt[i]; } - TexCoordType cWT(const int i) const { assert((*this).Base().WedgeTexEnabled); return (*this).Base().WTV[(*this).Index()].wt[i]; } + const TexCoordType& WT(const int i) const { assert((*this).Base().WedgeTexEnabled); return (*this).Base().WTV[(*this).Index()].wt[i]; } + const TexCoordType& cWT(const int i) const { assert((*this).Base().WedgeTexEnabled); return (*this).Base().WTV[(*this).Index()].wt[i]; } template void ImportData(const RightFaceType & rightF){ if(this->IsWedgeTexCoordEnabled() && rightF.IsWedgeTexCoordEnabled()) @@ -648,7 +690,8 @@ public: WedgeColorOcf(){ } typedef A WedgeColorType; WedgeColorType &WC(const int i) { assert((*this).Base().WedgeColorEnabled); return (*this).Base().WCV[(*this).Index()].wc[i]; } - const WedgeColorType cWC(const int i) const { assert((*this).Base().WedgeColorEnabled); return (*this).Base().WCV[(*this).Index()].wc[i]; } + const WedgeColorType& WC(const int i) const { assert((*this).Base().WedgeColorEnabled); return (*this).Base().WCV[(*this).Index()].wc[i]; } + const WedgeColorType& cWC(const int i) const { assert((*this).Base().WedgeColorEnabled); return (*this).Base().WCV[(*this).Index()].wc[i]; } template void ImportData(const RightFaceType & rightF){ if(this->IsWedgeColorEnabled() && rightF.IsWedgeColorEnabled()) @@ -668,7 +711,8 @@ public: WedgeNormalOcf(){ } typedef A WedgeNormalType; WedgeNormalType &WN(const int i) { assert((*this).Base().WedgeNormalEnabled); return (*this).Base().WNV[(*this).Index()].wn[i]; } - WedgeNormalType const &cWN(const int i) const { assert((*this).Base().WedgeNormalEnabled); return (*this).Base().WNV[(*this).Index()].wn[i]; } + const WedgeNormalType & WN(const int i) const { assert((*this).Base().WedgeNormalEnabled); return (*this).Base().WNV[(*this).Index()].wn[i]; } + const WedgeNormalType &cWN(const int i) const { assert((*this).Base().WedgeNormalEnabled); return (*this).Base().WNV[(*this).Index()].wn[i]; } template void ImportData(const RightFaceType & rightF){ if(this->IsWedgeNormalEnabled() && rightF.IsWedgeNormalEnabled()) From a1e1ba882f47249b3445e2ac6b31f7e288dff885 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 18 Mar 2021 17:23:27 +0100 Subject: [PATCH 073/140] 3ds const correctness --- wrap/io_trimesh/export_3ds.h | 273 +++++++++++++++++----------------- wrap/io_trimesh/export_obj.h | 2 +- wrap/io_trimesh/io_material.h | 21 +-- 3 files changed, 151 insertions(+), 145 deletions(-) diff --git a/wrap/io_trimesh/export_3ds.h b/wrap/io_trimesh/export_3ds.h index 69e4bd15..927cae0f 100644 --- a/wrap/io_trimesh/export_3ds.h +++ b/wrap/io_trimesh/export_3ds.h @@ -149,7 +149,7 @@ namespace io { /* function which saves in 3DS file format */ - static int SaveBinary(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) + static int SaveBinary(const SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) { if(m.vn > MAX_POLYGONS)//check max polygons return E_NOTNUMBERVERTVALID; @@ -222,28 +222,29 @@ namespace io { int nface = 0; if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) ) { - FaceIterator fi; - for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) - { - for(unsigned int k=0;k<3;k++) + for(const auto& f : m.face) { + if( !f.IsD() ) { - int i = GetIndexVertex(m, (*fi).V(k)); - vcg::TexCoord2 t = (*fi).WT(k); - if(!m.vert[i].IsD()) + for(unsigned int k=0;k<3;k++) { - if(AddDuplexVertexCoord(ListOfDuplexVert,Key(i,t))) + int i = GetIndexVertex(m, f.cV(k)); + vcg::TexCoord2 t = f.cWT(k); + if(!m.vert[i].IsD()) { - VectorOfVertexType.push_back((*(*fi).V(k))); - ListOfDuplexVert[Key(i,t)] = int(VectorOfVertexType.size()-1); - count++; + if(AddDuplexVertexCoord(ListOfDuplexVert,Key(i,t))) + { + VectorOfVertexType.push_back((*f.V(k))); + ListOfDuplexVert[Key(i,t)] = int(VectorOfVertexType.size()-1); + count++; + } } } - } - if (cb !=NULL) - (*cb)(100.0 * (float)++nface/(float)m.face.size(), "calc duplex vertex ..."); - else - return E_ABORTED; + if (cb !=NULL) + (*cb)(100.0 * (float)++nface/(float)m.face.size(), "calc duplex vertex ..."); + else + return E_ABORTED; + } } } @@ -267,7 +268,6 @@ namespace io { lib3ds_mesh_new_texel_list(mesh,m.vn + number_vertex_to_duplicate); //set number of textures int v_index = 0; - VertexIterator vi; //saves vert if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD )) { @@ -288,134 +288,139 @@ namespace io { } else { - VertRemap.resize(m.vert.size(),-1); - for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() ) - { - Lib3dsPoint point; - point.pos[0] = (*vi).P()[0]; - point.pos[1] = (*vi).P()[1]; - point.pos[2] = (*vi).P()[2]; + VertRemap.resize(m.vert.size(),-1); + unsigned int vi = 0; + for(const auto& v : m.vert) { + if( !v.IsD() ) + { + Lib3dsPoint point; + point.pos[0] = v.P()[0]; + point.pos[1] = v.P()[1]; + point.pos[2] = v.P()[2]; - mesh->pointL[v_index] = point; - VertRemap[vi-m.vert.begin()]=v_index; - if (cb !=NULL) - (*cb)(100.0 * (float)++current/(float)max, "writing vertices "); - else - return E_ABORTED; - v_index++; + mesh->pointL[v_index] = point; + VertRemap[vi]=v_index; + if (cb !=NULL) + (*cb)(100.0 * (float)++current/(float)max, "writing vertices "); + else + return E_ABORTED; + v_index++; + } + vi++; } } lib3ds_mesh_new_face_list (mesh, m.face.size());//set number of faces int f_index = 0;//face index //int t_index = 0;//texture index - FaceIterator fi; - for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) - { - vcg::TexCoord2 t0(0,0),t1(0,0),t2(0,0); - int i0 = GetIndexVertex(m, (*fi).V(0)); - int i1 = GetIndexVertex(m, (*fi).V(1)); - int i2 = GetIndexVertex(m, (*fi).V(2)); - if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) ) + for(const auto& f : m.face) { + if( !f.IsD() ) { - t0 = (*fi).WT(0); - t1 = (*fi).WT(1); - t2 = (*fi).WT(2); - } - - Lib3dsFace face; - if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD )) - { - face.points[0] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i0,t0)); - face.points[1] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i1,t1)); - face.points[2] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i2,t2)); - } - else - { - face.points[0] = VertRemap[i0]; - face.points[1] = VertRemap[i1]; - face.points[2] = VertRemap[i2]; - } - - //saves coord textures - if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) ) - { - mesh->texelL[face.points[0]][0] = t0.u(); - mesh->texelL[face.points[0]][1] = t0.v(); - mesh->texelL[face.points[1]][0] = t1.u(); - mesh->texelL[face.points[1]][1] = t1.v(); - mesh->texelL[face.points[2]][0] = t2.u(); - mesh->texelL[face.points[2]][1] = t2.v(); - } - - if(mask & vcg::tri::io::Mask::IOM_FACEFLAGS) - face.flags = 0; - - face.smoothing = 10; - - if((mask & vcg::tri::io::Mask::IOM_FACENORMAL) | (mask & vcg::tri::io::Mask::IOM_WEDGNORMAL) ) - { - face.normal[0] = (*fi).N()[0]; - face.normal[1] = (*fi).N()[1]; - face.normal[2] = (*fi).N()[2]; - } - - if((mask & vcg::tri::io::Mask::IOM_FACECOLOR) | (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD)) - { - int material_index = vcg::tri::io::Materials::CreateNewMaterial(m, materials, fi); - if(material_index == (int)materials.size()) + vcg::TexCoord2 t0(0,0),t1(0,0),t2(0,0); + int i0 = GetIndexVertex(m, f.cV(0)); + int i1 = GetIndexVertex(m, f.cV(1)); + int i2 = GetIndexVertex(m, f.cV(2)); + if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) ) { - Lib3dsMaterial *material = lib3ds_material_new();//creates a new material - - std::string name = qnamematerial.arg(material_index-1).toStdString(); - strcpy(material->name,name.c_str());//copy new name of material + t0 = f.cWT(0); + t1 = f.cWT(1); + t2 = f.cWT(2); + } - if(mask & vcg::tri::io::Mask::IOM_FACECOLOR) - { - //ambient - material->ambient[0] = materials[materials.size()-1].Ka[0]; - material->ambient[1] = materials[materials.size()-1].Ka[1]; - material->ambient[2] = materials[materials.size()-1].Ka[2]; - material->ambient[3] = materials[materials.size()-1].Tr; - - //diffuse - material->diffuse[0] = materials[materials.size()-1].Kd[0]; - material->diffuse[1] = materials[materials.size()-1].Kd[1]; - material->diffuse[2] = materials[materials.size()-1].Kd[2]; - material->diffuse[3] = materials[materials.size()-1].Tr; - - //specular - material->specular[0] = materials[materials.size()-1].Ks[0]; - material->specular[1] = materials[materials.size()-1].Ks[1]; - material->specular[2] = materials[materials.size()-1].Ks[2]; - material->specular[3] = materials[materials.size()-1].Tr; - - //shininess - material->shininess = materials[materials.size()-1].Ns; - } - - //texture - if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) ) - strcpy(material->texture1_map.name,materials[materials.size()-1].map_Kd.c_str()); - - lib3ds_file_insert_material(file,material);//inserts the material inside the file - strcpy(face.material,name.c_str()); + Lib3dsFace face; + if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD )) + { + face.points[0] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i0,t0)); + face.points[1] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i1,t1)); + face.points[2] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i2,t2)); } else - { - std::string name = qnamematerial.arg(material_index).toStdString(); - strcpy(face.material,name.c_str());//set name of material + { + face.points[0] = VertRemap[i0]; + face.points[1] = VertRemap[i1]; + face.points[2] = VertRemap[i2]; } + + //saves coord textures + if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) ) + { + mesh->texelL[face.points[0]][0] = t0.u(); + mesh->texelL[face.points[0]][1] = t0.v(); + mesh->texelL[face.points[1]][0] = t1.u(); + mesh->texelL[face.points[1]][1] = t1.v(); + mesh->texelL[face.points[2]][0] = t2.u(); + mesh->texelL[face.points[2]][1] = t2.v(); + } + + if(mask & vcg::tri::io::Mask::IOM_FACEFLAGS) + face.flags = 0; + + face.smoothing = 10; + + if((mask & vcg::tri::io::Mask::IOM_FACENORMAL) | (mask & vcg::tri::io::Mask::IOM_WEDGNORMAL) ) + { + face.normal[0] = f.cN()[0]; + face.normal[1] = f.cN()[1]; + face.normal[2] = f.cN()[2]; + } + + if((mask & vcg::tri::io::Mask::IOM_FACECOLOR) | (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD)) + { + int material_index = vcg::tri::io::Materials::CreateNewMaterial(m, materials, f); + if(material_index == (int)materials.size()) + { + Lib3dsMaterial *material = lib3ds_material_new();//creates a new material + + std::string name = qnamematerial.arg(material_index-1).toStdString(); + strcpy(material->name,name.c_str());//copy new name of material + + if(mask & vcg::tri::io::Mask::IOM_FACECOLOR) + { + //ambient + material->ambient[0] = materials[materials.size()-1].Ka[0]; + material->ambient[1] = materials[materials.size()-1].Ka[1]; + material->ambient[2] = materials[materials.size()-1].Ka[2]; + material->ambient[3] = materials[materials.size()-1].Tr; + + //diffuse + material->diffuse[0] = materials[materials.size()-1].Kd[0]; + material->diffuse[1] = materials[materials.size()-1].Kd[1]; + material->diffuse[2] = materials[materials.size()-1].Kd[2]; + material->diffuse[3] = materials[materials.size()-1].Tr; + + //specular + material->specular[0] = materials[materials.size()-1].Ks[0]; + material->specular[1] = materials[materials.size()-1].Ks[1]; + material->specular[2] = materials[materials.size()-1].Ks[2]; + material->specular[3] = materials[materials.size()-1].Tr; + + //shininess + material->shininess = materials[materials.size()-1].Ns; + } + + //texture + if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) ) + strcpy(material->texture1_map.name,materials[materials.size()-1].map_Kd.c_str()); + + lib3ds_file_insert_material(file,material);//inserts the material inside the file + strcpy(face.material,name.c_str()); + } + else + { + std::string name = qnamematerial.arg(material_index).toStdString(); + strcpy(face.material,name.c_str());//set name of material + } + } + + mesh->faceL[f_index]=face; + + if (cb !=NULL) + (*cb)(100.0 * (float)++current/(float)max, "writing faces "); + else + return E_ABORTED; + f_index++; + } - - mesh->faceL[f_index]=face; - - if (cb !=NULL) - (*cb)(100.0 * (float)++current/(float)max, "writing faces "); - else - return E_ABORTED; - f_index++; - } lib3ds_file_insert_mesh(file, mesh);//inserts the Mesh into file @@ -435,7 +440,7 @@ namespace io { /* function which saves in 3DS format */ - static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) + static int Save(const SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) { return SaveBinary(m,filename,mask,cb); } @@ -443,7 +448,7 @@ namespace io { /* returns index of the vertex */ - inline static int GetIndexVertex(SaveMeshType &m, VertexType *p) + inline static int GetIndexVertex(const SaveMeshType &m, VertexType *p) { return p-&*(m.vert.begin()); } diff --git a/wrap/io_trimesh/export_obj.h b/wrap/io_trimesh/export_obj.h index c34d4b80..47597ee0 100644 --- a/wrap/io_trimesh/export_obj.h +++ b/wrap/io_trimesh/export_obj.h @@ -218,7 +218,7 @@ public: { int index=-1; if(useMaterialAttribute) index = materialIndexHandle[fi]; - else index = Materials::CreateNewMaterial(m,materialVec,fi); + else index = Materials::CreateNewMaterial(m,materialVec,*fi); if(index != curMatIndex) { fprintf(fp,"\nusemtl material_%d\n", index); diff --git a/wrap/io_trimesh/io_material.h b/wrap/io_trimesh/io_material.h index 993be356..9471a5bd 100644 --- a/wrap/io_trimesh/io_material.h +++ b/wrap/io_trimesh/io_material.h @@ -85,7 +85,8 @@ struct Material template class Materials { -public: +public: + typedef typename SaveMeshType::FaceType FaceType; typedef typename SaveMeshType::FaceIterator FaceIterator; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::VertexType VertexType; @@ -93,20 +94,20 @@ public: /* creates a new meterial */ - inline static int CreateNewMaterial(SaveMeshType &m, std::vector &materials, FaceIterator &fi) - { + inline static int CreateNewMaterial(const SaveMeshType &m, std::vector &materials, const FaceType& f) + { Material mtl; - + if(HasPerFaceColor(m)){ - mtl.Kd = Point3f((float)((*fi).C()[0])/255.0f,(float)((*fi).C()[1])/255.0f,(float)((*fi).C()[2])/255.0f);//diffuse - mtl.Tr = (float)((*fi).C()[3])/255.0f;//alpha + mtl.Kd = Point3f((float)(f.C()[0])/255.0f,(float)(f.C()[1])/255.0f,(float)(f.C()[2])/255.0f);//diffuse + mtl.Tr = (float)(f.C()[3])/255.0f;//alpha } - - if(m.textures.size() && (*fi).WT(0).n() >=0 ) - mtl.map_Kd = m.textures[(*fi).WT(0).n()]; + + if(m.textures.size() && f.WT(0).n() >=0 ) + mtl.map_Kd = m.textures[f.WT(0).n()]; else mtl.map_Kd = ""; - + int matInd = MaterialsCompare(materials,mtl); if(matInd == -1) { From 0a2ed11ac24f9f53564b8792ed9ce278126e68ff Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 18 Mar 2021 18:21:59 +0100 Subject: [PATCH 074/140] (partial) ply const correctness --- vcg/container/simple_temporary_data.h | 8 +++-- vcg/simplex/vertex/component.h | 14 +++++++++ wrap/io_trimesh/export_ply.h | 42 ++++++++++++++++----------- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/vcg/container/simple_temporary_data.h b/vcg/container/simple_temporary_data.h index 979e4357..c1f26fa5 100644 --- a/vcg/container/simple_temporary_data.h +++ b/vcg/container/simple_temporary_data.h @@ -114,16 +114,16 @@ public: typedef SimpleTempData SimpTempDataType; typedef ATTR_TYPE AttrType; - STL_CONT &c; + const STL_CONT &c; VectorNBW data; int padding; - SimpleTempData(STL_CONT &_c) : c(_c), padding(0) + SimpleTempData(const STL_CONT &_c) : c(_c), padding(0) { data.reserve(c.capacity()); data.resize(c.size()); }; - SimpleTempData(STL_CONT &_c, const ATTR_TYPE &val) : c(_c) + SimpleTempData(const STL_CONT &_c, const ATTR_TYPE &val) : c(_c) { data.reserve(c.capacity()); data.resize(c.size()); @@ -142,11 +142,13 @@ public: // access to data ATTR_TYPE &operator[](const typename STL_CONT::value_type &v) { return data[&v - &*c.begin()]; } ATTR_TYPE &operator[](const typename STL_CONT::value_type *v) { return data[v - &*c.begin()]; } + ATTR_TYPE &operator[](const typename STL_CONT::const_iterator &cont) { return data[&(*cont) - &*c.begin()]; } ATTR_TYPE &operator[](const typename STL_CONT::iterator &cont) { return data[&(*cont) - &*c.begin()]; } ATTR_TYPE &operator[](size_t i) { return data[i]; } const ATTR_TYPE &operator[](const typename STL_CONT::value_type &v) const { return data[&v - &*c.begin()]; } const ATTR_TYPE &operator[](const typename STL_CONT::value_type *v) const { return data[v - &*c.begin()]; } + const ATTR_TYPE &operator[](const typename STL_CONT::const_iterator &cont) const { return data[&(*cont) - &*c.begin()]; } const ATTR_TYPE &operator[](const typename STL_CONT::iterator &cont) const { return data[&(*cont) - &*c.begin()]; } const ATTR_TYPE &operator[](size_t i) const { return data[i]; } diff --git a/vcg/simplex/vertex/component.h b/vcg/simplex/vertex/component.h index 1914dbbd..f4cab3c9 100644 --- a/vcg/simplex/vertex/component.h +++ b/vcg/simplex/vertex/component.h @@ -49,30 +49,35 @@ template class EmptyCore: public TT { public: typedef int FlagType; int &Flags() { assert(0); static int dummyflags(0); return dummyflags; } + int Flags() const { return 0; } int cFlags() const { return 0; } static bool HasFlags() { return false; } typedef vcg::Point3f CoordType; typedef CoordType::ScalarType ScalarType; CoordType &P() { assert(0); static CoordType coord(0, 0, 0); return coord; } + CoordType P() const { assert(0); static CoordType coord(0, 0, 0); assert(0); return coord; } CoordType cP() const { assert(0); static CoordType coord(0, 0, 0); assert(0); return coord; } static bool HasCoord() { return false; } inline bool IsCoordEnabled() const { return TT::VertexType::HasCoord();} typedef vcg::Point3s NormalType; NormalType &N() { assert(0); static NormalType dummy_normal(0, 0, 0); return dummy_normal; } + NormalType N() const { assert(0); static NormalType dummy_normal(0, 0, 0); return dummy_normal; } NormalType cN() const { assert(0); static NormalType dummy_normal(0, 0, 0); return dummy_normal; } static bool HasNormal() { return false; } inline bool IsNormalEnabled() const { return TT::VertexType::HasNormal();} typedef float QualityType; QualityType &Q() { assert(0); static QualityType dummyQuality(0); return dummyQuality; } + QualityType Q() const { assert(0); static QualityType dummyQuality(0); return dummyQuality; } QualityType cQ() const { assert(0); static QualityType dummyQuality(0); return dummyQuality; } static bool HasQuality() { return false; } inline bool IsQualityEnabled() const { return TT::VertexType::HasQuality();} typedef vcg::Color4b ColorType; ColorType &C() { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } + ColorType C() const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } ColorType cC() const { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } static bool HasColor() { return false; } inline bool IsColorEnabled() const { return TT::VertexType::HasColor();} @@ -80,18 +85,21 @@ public: typedef int MarkType; void InitIMark() { } int cIMark() const { assert(0); static int tmp=-1; return tmp;} + int IMark() const { assert(0); static int tmp=-1; return tmp;} int &IMark() { assert(0); static int tmp=-1; return tmp;} static bool HasMark() { return false; } inline bool IsMarkEnabled() const { return TT::VertexType::HasMark();} typedef ScalarType RadiusType; RadiusType &R() { static ScalarType v = 0.0; assert(0 && "the radius component is not available"); return v; } + RadiusType R() const { static const ScalarType v = 0.0; assert(0 && "the radius component is not available"); return v; } RadiusType cR() const { static const ScalarType v = 0.0; assert(0 && "the radius component is not available"); return v; } static bool HasRadius() { return false; } inline bool IsRadiusEnabled() const { return TT::VertexType::HasRadius();} typedef vcg::TexCoord2 TexCoordType; TexCoordType &T() { static TexCoordType dummy_texcoord; assert(0); return dummy_texcoord; } + TexCoordType T() const { static TexCoordType dummy_texcoord; assert(0); return dummy_texcoord; } TexCoordType cT() const { static TexCoordType dummy_texcoord; assert(0); return dummy_texcoord; } static bool HasTexCoord() { return false; } inline bool IsTexCoordEnabled() const { return TT::VertexType::HasTexCoord();} @@ -151,17 +159,23 @@ public: typedef Point2f CurvatureType; float &Kh() { static float dummy = 0.f; assert(0);return dummy;} float &Kg() { static float dummy = 0.f; assert(0);return dummy;} + float Kh() const { static float dummy = 0.f; assert(0); return dummy;} + float Kg() const { static float dummy = 0.f; assert(0); return dummy;} float cKh() const { static float dummy = 0.f; assert(0); return dummy;} float cKg() const { static float dummy = 0.f; assert(0); return dummy;} typedef CurvatureDirBaseType CurvatureDirType; CurVecType &PD1() {static CurVecType v(0,0,0); assert(0);return v;} CurVecType &PD2() {static CurVecType v(0,0,0); assert(0);return v;} + CurVecType PD1() const {static CurVecType v(0,0,0); assert(0);return v;} + CurVecType PD2() const {static CurVecType v(0,0,0); assert(0);return v;} CurVecType cPD1() const {static CurVecType v(0,0,0); assert(0);return v;} CurVecType cPD2() const {static CurVecType v(0,0,0); assert(0);return v;} CurScalarType &K1() { static ScalarType v = 0.0;assert(0);return v;} CurScalarType &K2() { static ScalarType v = 0.0;assert(0);return v;} + CurScalarType K1() const {static ScalarType v = 0.0;assert(0);return v;} + CurScalarType K2() const {static ScalarType v = 0.0;assert(0);return v;} CurScalarType cK1() const {static ScalarType v = 0.0;assert(0);return v;} CurScalarType cK2() const {static ScalarType v = 0.0;assert(0);return v;} diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index c1f45e01..05364d73 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -70,30 +70,30 @@ namespace vcg { public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; - typedef typename SaveMeshType::VertexPointer VertexPointer; + typedef typename SaveMeshType::ConstVertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; - typedef typename SaveMeshType::FacePointer FacePointer; - typedef typename SaveMeshType::VertexIterator VertexIterator; - typedef typename SaveMeshType::FaceIterator FaceIterator; - typedef typename SaveMeshType::EdgeIterator EdgeIterator; + typedef typename SaveMeshType::ConstFacePointer FacePointer; + typedef typename SaveMeshType::ConstVertexIterator VertexIterator; + typedef typename SaveMeshType::ConstFaceIterator FaceIterator; + typedef typename SaveMeshType::ConstEdgeIterator EdgeIterator; typedef typename vcg::Shot::ScalarType ShotScalarType; - static int Save(SaveMeshType &m, const char * filename, bool binary=true) + static int Save(const SaveMeshType &m, const char * filename, bool binary=true) { PlyInfo pi; return Save(m,filename,binary,pi); } - static int Save(SaveMeshType &m, const char * filename, int savemask, bool binary = true, CallBackPos *cb=0 ) + static int Save(const SaveMeshType &m, const char * filename, int savemask, bool binary = true, CallBackPos *cb=0 ) { PlyInfo pi; pi.mask=savemask; return Save(m,filename,binary,pi,cb); } - static int Save(SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi, CallBackPos *cb=0) // V1.0 + static int Save(const SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi, CallBackPos *cb=0) // V1.0 { FILE * fpout; const char * hbin = "binary_little_endian"; @@ -437,14 +437,20 @@ namespace vcg { if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS) ) fwrite(&(vp->Flags()),sizeof(int),1,fpout); - if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) - fwrite(&( vp->C() ),sizeof(char),4,fpout); + if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ){ + auto c = vp->C(); + fwrite(&c,sizeof(char),4,fpout); + } - if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) - fwrite(&( vp->Q() ),sizeof(typename VertexType::QualityType),1,fpout); + if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ){ + auto q = vp->Q(); + fwrite(&q, sizeof(typename VertexType::QualityType),1,fpout); + } - if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ) - fwrite(&( vp->R() ),sizeof(typename VertexType::RadiusType),1,fpout); + if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ){ + auto r = vp->R(); + fwrite(&r,sizeof(typename VertexType::RadiusType),1,fpout); + } if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) { @@ -489,7 +495,7 @@ namespace vcg { fprintf(fpout,"%.*g %.*g %.*g " ,DGT,vp->P()[0],DGT,vp->P()[1],DGT,vp->P()[2]); if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) - fprintf(fpout,"%.*g %.*g %.*g " ,DGT,ScalarType(vp->N()[0]),DGT,ScalarType(vp->N()[1]),DGT,ScalarType(vp->N()[2])); + fprintf(fpout,"%.*g %.*g %.*g " ,DGT,ScalarType(vp->N()[0]),DGT,ScalarType(vp->N()[1]),DGT,ScalarType(vp->N()[2])); if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS)) fprintf(fpout,"%d ",vp->Flags()); @@ -571,8 +577,10 @@ namespace vcg { fwrite(&b3char,sizeof(char),1,fpout); fwrite(vv,sizeof(int),3,fpout); - if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) ) - fwrite(&(fp->Flags()),sizeof(int),1,fpout); + if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) ){ + auto fl = fp->Flags(); + fwrite(&fl,sizeof(int),1,fpout); + } if( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // Note that you can save VT as WT if you really want it... { From 3d0e74e4721e2762da9ae768976ed0c70c30c4d2 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 18 Mar 2021 18:30:54 +0100 Subject: [PATCH 075/140] stl const correctness --- vcg/space/color4.h | 8 ++++---- wrap/io_trimesh/export_stl.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vcg/space/color4.h b/vcg/space/color4.h index f9d2b9d0..d97e7480 100644 --- a/vcg/space/color4.h +++ b/vcg/space/color4.h @@ -259,8 +259,8 @@ inline static Color4 ColorRamp(const float &minf,const float &maxf ,float v ) return rc; } -inline static unsigned short ToUnsignedB5G5R5(Color4 &) { return 0;} -inline static unsigned short ToUnsignedR5G5B5(Color4 &) { return 0;} +inline static unsigned short ToUnsignedB5G5R5(const Color4 &) { return 0;} +inline static unsigned short ToUnsignedR5G5B5(const Color4 &) { return 0;} inline static Color4 FromUnsignedB5G5R5(unsigned short) { @@ -420,7 +420,7 @@ typedef Color4 Color4d; template<> -inline unsigned short Color4::ToUnsignedB5G5R5(Color4 &cc) +inline unsigned short Color4::ToUnsignedB5G5R5(const Color4 &cc) { unsigned short r = cc[0]/8; unsigned short g = cc[1]/8; @@ -430,7 +430,7 @@ inline unsigned short Color4::ToUnsignedB5G5R5(Color4 -inline unsigned short Color4::ToUnsignedR5G5B5(Color4 &cc) +inline unsigned short Color4::ToUnsignedR5G5B5(const Color4 &cc) { unsigned short r = cc[0]/8; unsigned short g = cc[1]/8; diff --git a/wrap/io_trimesh/export_stl.h b/wrap/io_trimesh/export_stl.h index 50859273..0ed6d9c9 100644 --- a/wrap/io_trimesh/export_stl.h +++ b/wrap/io_trimesh/export_stl.h @@ -75,14 +75,14 @@ public: typedef typename SaveMeshType::FaceType FaceType; typedef unsigned short CallBackSTLFaceAttribute(const SaveMeshType &m, const FaceType &f); -static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *) +static int Save(const SaveMeshType &m, const char * filename, const int &mask, CallBackPos *) { return Save(m,filename,true,mask); } -static int Save(SaveMeshType &m, const char * filename , bool binary =true, int mask=0, const char *objectname=0, bool magicsMode=0) +static int Save(const SaveMeshType &m, const char * filename , bool binary =true, int mask=0, const char *objectname=0, bool magicsMode=0) { - typedef typename SaveMeshType::FaceIterator FaceIterator; + typedef typename SaveMeshType::ConstFaceIterator FaceIterator; FILE *fp; fp = fopen(filename,"wb"); From abcde4bbed4945d9c29424cd45cfba0196fd169f Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 18 Mar 2021 18:54:15 +0100 Subject: [PATCH 076/140] vrml const correctness --- wrap/io_trimesh/export_vrml.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wrap/io_trimesh/export_vrml.h b/wrap/io_trimesh/export_vrml.h index 4348ef86..117fbd4a 100644 --- a/wrap/io_trimesh/export_vrml.h +++ b/wrap/io_trimesh/export_vrml.h @@ -57,15 +57,15 @@ namespace vcg { class ExporterWRL { public: - typedef typename SaveMeshType::VertexPointer VertexPointer; + typedef typename SaveMeshType::ConstVertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; - typedef typename SaveMeshType::VertexIterator VertexIterator; - typedef typename SaveMeshType::FaceIterator FaceIterator; + typedef typename SaveMeshType::ConstVertexIterator VertexIterator; + typedef typename SaveMeshType::ConstFaceIterator FaceIterator; ///Standard call for saving a mesh - static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos * /*cb=0*/) + static int Save(const SaveMeshType &m, const char * filename, const int &mask, CallBackPos * /*cb=0*/) { FILE *fp; fp = fopen(filename,"wb"); @@ -321,4 +321,4 @@ namespace vcg { } // end Namespace tri } // end Namespace vcg -#endif \ No newline at end of file +#endif From 8f953efd0477bf0893d4c6045fafb121bd0065a2 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 19 Mar 2021 12:16:01 +0100 Subject: [PATCH 077/140] CountBitLargePolygons const correctness --- vcg/complex/algorithms/clean.h | 49 ++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/vcg/complex/algorithms/clean.h b/vcg/complex/algorithms/clean.h index a52c8d75..b38b01d9 100644 --- a/vcg/complex/algorithms/clean.h +++ b/vcg/complex/algorithms/clean.h @@ -168,6 +168,7 @@ public: typedef CleanMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; + typedef typename MeshType::ConstVertexPointer ConstVertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::ConstVertexIterator ConstVertexIterator; typedef typename MeshType::EdgeIterator EdgeIterator; @@ -931,30 +932,38 @@ public: } /** - * The number of polygonal faces is - * FN - EN_f (each faux edge hides exactly one triangular face or in other words a polygon of n edges has n-3 faux edges.) - * In the general case where a The number of polygonal faces is - * FN - EN_f + VN_f - * where: - * EN_f is the number of faux edges. - * VN_f is the number of faux vertices (e.g vertices completely surrounded by faux edges) - * as a intuitive proof think to a internal vertex that is collapsed onto a border of a polygon: - * it deletes 2 faces, 1 faux edges and 1 vertex so to keep the balance you have to add back the removed vertex. - */ - static int CountBitLargePolygons(MeshType &m) + * The number of polygonal faces is + * FN - EN_f (each faux edge hides exactly one triangular face or in other words a polygon of n edges has n-3 faux edges.) + * In the general case where a The number of polygonal faces is + * FN - EN_f + VN_f + * where: + * EN_f is the number of faux edges. + * VN_f is the number of faux vertices (e.g vertices completely surrounded by faux edges) + * as a intuitive proof think to a internal vertex that is collapsed onto a border of a polygon: + * it deletes 2 faces, 1 faux edges and 1 vertex so to keep the balance you have to add back the removed vertex. + */ + static int CountBitLargePolygons(const MeshType &m) { - tri::RequirePerFaceFlags(m); - UpdateFlags::VertexSetV(m); + //note - using unordered_map to set visited vertices because + //the mesh is const (before, the function used vertex flags...). + //could be used std::vector if the vertex has the Index() + //member function... + std::unordered_map vertVisited; + for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!vi->IsD()) vertVisited[&(*vi)] = true; + // First loop Clear all referenced vertices - for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) - for(int i=0;i<3;++i) fi->V(i)->ClearV(); + for(int i=0;i<3;++i){ + vertVisited[fi->V(i)] = false; + } // Second Loop, count (twice) faux edges and mark all vertices touched by non faux edges // (e.g vertexes on the boundary of a polygon) int countE = 0; - for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { for(int i=0;i<3;++i) { @@ -962,16 +971,16 @@ public: countE++; else { - fi->V0(i)->SetV(); - fi->V1(i)->SetV(); + vertVisited[fi->V0(i)] = true; + vertVisited[fi->V1(i)] = true; } } } // Third Loop, count the number of referenced vertexes that are completely surrounded by faux edges. int countV = 0; - for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if (!vi->IsD() && !vi->IsV()) countV++; + for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!vi->IsD() && !(vertVisited[&(*vi)])) countV++; return m.fn - countE/2 + countV ; } From 8b369752486b3b62c752564461910b41db761adb Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 19 Mar 2021 12:58:38 +0100 Subject: [PATCH 078/140] dxf, gts and partial obj const correctness --- wrap/io_trimesh/export_dxf.h | 10 +++++----- wrap/io_trimesh/export_gts.h | 35 +++++++++++++++++++---------------- wrap/io_trimesh/export_obj.h | 10 ++++++---- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/wrap/io_trimesh/export_dxf.h b/wrap/io_trimesh/export_dxf.h index 7f4e8557..08d21bb0 100644 --- a/wrap/io_trimesh/export_dxf.h +++ b/wrap/io_trimesh/export_dxf.h @@ -41,7 +41,7 @@ class ExporterDXF typedef typename SaveMeshType::CoordType CoordType; public: ///Standard call for saving a mesh - static int Save(SaveMeshType &m, const char * filename) + static int Save(const SaveMeshType &m, const char * filename) { if(m.fn==0 && m.en != 0) return SaveEdge(m,filename); @@ -55,7 +55,7 @@ public: fprintf(o,"2\n"); fprintf(o,"ENTITIES\n"); - typename SaveMeshType::FaceIterator fi; + typename SaveMeshType::ConstFaceIterator fi; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) { if (!fi->IsD()) @@ -109,7 +109,7 @@ public: } - static bool SaveEdge(SaveMeshType &m, const char * filename) + static bool SaveEdge(const SaveMeshType &m, const char * filename) { FILE * o = fopen(filename,"w"); if(o==NULL) return 1; @@ -121,7 +121,7 @@ public: fprintf(o,"2\n"); fprintf(o,"ENTITIES\n"); - typename SaveMeshType::EdgeIterator ei; + typename SaveMeshType::ConstEdgeIterator ei; for(ei=m.edge.begin(); ei!=m.edge.end();++ei) { CoordType p1 = (*ei).V(0)->P(); @@ -155,7 +155,7 @@ public: return true; } - static bool writeHeader(FILE* o, SaveMeshType &mp) + static bool writeHeader(FILE* o, const SaveMeshType &mp) { // standard DXF header // most of data is meaningless, but required by a lot of importers diff --git a/wrap/io_trimesh/export_gts.h b/wrap/io_trimesh/export_gts.h index 4af571cb..f08719f0 100644 --- a/wrap/io_trimesh/export_gts.h +++ b/wrap/io_trimesh/export_gts.h @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -45,15 +46,15 @@ namespace vcg { { public: - typedef typename SaveMeshType::VertexPointer VertexPointer; + typedef typename SaveMeshType::ConstVertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; - typedef typename SaveMeshType::FacePointer FacePointer; - typedef typename SaveMeshType::VertexIterator VertexIterator; - typedef typename SaveMeshType::FaceIterator FaceIterator; + typedef typename SaveMeshType::ConstFacePointer FacePointer; + typedef typename SaveMeshType::ConstVertexIterator VertexIterator; + typedef typename SaveMeshType::ConstFaceIterator FaceIterator; - static int Save(SaveMeshType &m, const char * filename, int /*mask*/ ) + static int Save(const SaveMeshType &m, const char * filename, int /*mask*/ ) { QFile device(filename); if (!device.open(QFile::WriteOnly)) @@ -62,17 +63,19 @@ namespace vcg { QTextStream stream(&device); // update vertex indices - std::vector FlagV; + //std::vector FlagV; + std::unordered_map vertFlags; VertexPointer vp; VertexIterator vi; int j; for(j=0,vi=m.vert.begin(); vi!=m.vert.end(); ++vi) { vp = &(*vi); - FlagV.push_back(vp->Flags()); + //FlagV.push_back(vp->Flags()); if (!vp->IsD()) { - vp->Flags() = j; + vertFlags[vp] = j; + //vp->Flags() = j; j++; } } @@ -94,8 +97,8 @@ namespace vcg { { for (int k=0; k<3; ++k) { - int a = fp->cV(k)->Flags(); - int b = fp->cV((k+1)%3)->Flags(); + int a = vertFlags[fp->cV(k)];//fp->cV(k)->Flags(); + int b = vertFlags[fp->cV((k+1)%3)];//fp->cV((k+1)%3)->Flags(); if (a>b) std::swap(a,b); Edge e(a,b); @@ -132,8 +135,8 @@ namespace vcg { { for (int k=0; k<3; ++k) { - int a = fp->cV(k)->Flags(); - int b = fp->cV((k+1)%3)->Flags(); + int a = vertFlags[fp->cV(k)];//fp->cV(k)->Flags(); + int b = vertFlags[fp->cV((k+1)%3)];//fp->cV((k+1)%3)->Flags(); if (a>b) std::swap(a,b); Edge e(a,b); @@ -154,8 +157,8 @@ namespace vcg { { for (int k=0; k<3; ++k) { - int a = fp->cV(k)->Flags(); - int b = fp->cV((k+1)%3)->Flags(); + int a = vertFlags[fp->cV(k)];//fp->cV(k)->Flags(); + int b = vertFlags[fp->cV((k+1)%3)];//fp->cV((k+1)%3)->Flags(); if (a>b) std::swap(a,b); Edge e(a,b); @@ -170,8 +173,8 @@ namespace vcg { } // Recupera i flag originali - for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi) - (*vi).Flags()=FlagV[j++]; + //for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi) + // (*vi).Flags()=FlagV[j++]; int result = 0; diff --git a/wrap/io_trimesh/export_obj.h b/wrap/io_trimesh/export_obj.h index 47597ee0..ce0626fe 100644 --- a/wrap/io_trimesh/export_obj.h +++ b/wrap/io_trimesh/export_obj.h @@ -42,7 +42,9 @@ class ExporterOBJ { public: typedef typename SaveMeshType::FaceIterator FaceIterator; + typedef typename SaveMeshType::ConstFaceIterator ConstFaceIterator; typedef typename SaveMeshType::EdgeIterator EdgeIterator; + typedef typename SaveMeshType::ConstEdgeIterator ConstEdgeIterator; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::ScalarType ScalarType; @@ -212,7 +214,7 @@ public: int curMatIndex = -1; std::vector materialVec; //used if we do not have material attributes - for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) + for(ConstFaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) { if((mask & Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) || (mask & Mask::IOM_VERTTEXCOORD)) { @@ -269,7 +271,7 @@ public: } // end for faces - for(EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) if( !(*ei).IsD() ) + for(ConstEdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) if( !(*ei).IsD() ) { fprintf(fp,"l %i %i\n", VertexId[tri::Index(m, (*ei).V(0))] + 1, @@ -312,7 +314,7 @@ public: /* returns index of the vertex normal */ - inline static int GetIndexVertexNormal(SaveMeshType &/*m*/, std::map &mapNormToInt, const CoordType &norm ) + inline static int GetIndexVertexNormal(const SaveMeshType &/*m*/, std::map &mapNormToInt, const CoordType &norm ) { typename std::map::iterator iter= mapNormToInt.find(norm); if(iter != mapNormToInt.end()) return (*iter).second; @@ -358,7 +360,7 @@ public: adds a new index to the normal per vertex if it is the first time which is otherwise met does not execute anything */ - inline static bool AddNewNormalVertex(typename std::map &m, CoordType &n ,int value) + inline static bool AddNewNormalVertex(typename std::map &m, const CoordType &n ,int value) { int index = m[n]; if(index==0){m[n]=value;return true;} From 82ce871150b1aaa9a63eb670fa782d0a989c9868 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 19 Mar 2021 13:16:48 +0100 Subject: [PATCH 079/140] const GetAllAttributeHandle --- vcg/complex/allocate.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 5ada3e88..fb088206 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1550,7 +1550,7 @@ public: \returns the name of all attributes with a non-empy name. */ template - static void GetAllPerVertexAttribute(MeshType & m, std::vector &all){ + static void GetAllPerVertexAttribute(const MeshType & m, std::vector &all){ all.clear(); typename std::set ::const_iterator i; for(i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i ) @@ -1847,7 +1847,7 @@ public: } template - static void GetAllPerFaceAttribute(MeshType & m, std::vector &all){ + static void GetAllPerFaceAttribute(const MeshType & m, std::vector &all){ all.clear(); typename std::set :: const_iterator i; for(i = m.face_attr.begin(); i != m.face_attr.end(); ++i ) From f83bdf081554c3b6ac77a7a1cfd9d31040b3d8b6 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Tue, 23 Mar 2021 01:06:28 +0100 Subject: [PATCH 080/140] quick and dirty fix for polygon import from trimesh --- vcg/complex/algorithms/polygon_support.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/polygon_support.h b/vcg/complex/algorithms/polygon_support.h index c6df0d8e..bce0d219 100644 --- a/vcg/complex/algorithms/polygon_support.h +++ b/vcg/complex/algorithms/polygon_support.h @@ -141,7 +141,8 @@ namespace tri { { std::vector vs;// vertices of the polygon ExtractPolygon(&*tfi,vs); - std::reverse(vs.begin(),vs.end()); + if (vs.size() > 3) + std::reverse(vs.begin(), vs.end()); //now vs contains all the vertices of the polygon (still in the trimesh) if (vs.size()==0)continue; typename PolyMeshType::FaceIterator pfi = tri::Allocator::AddFaces(pm,1); From bf6c48f9bead3ef3d030ccd6f9846180e6e235df Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 23 Mar 2021 12:59:45 +0100 Subject: [PATCH 081/140] fix VectorNBW bool specialization with const --- vcg/container/simple_temporary_data.h | 35 +++++++++++++++------------ 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/vcg/container/simple_temporary_data.h b/vcg/container/simple_temporary_data.h index c1f26fa5..059d65c7 100644 --- a/vcg/container/simple_temporary_data.h +++ b/vcg/container/simple_temporary_data.h @@ -24,6 +24,11 @@ #ifndef __VCGLIB_SIMPLE__ #define __VCGLIB_SIMPLE__ +#include +#include +#include +#include + namespace vcg { @@ -42,16 +47,16 @@ public: virtual void CopyValue(const size_t to, const size_t from, const SimpleTempDataBase *other) = 0; }; -template -class VectorNBW : public std::vector +template +class VectorNBW : public std::vector { }; -template <> -class VectorNBW +template +class VectorNBW { public: - VectorNBW() : data(0), datasize(0), datareserve(0) {} + VectorNBW() : data(nullptr), datasize(0), datareserve(0) {} ~VectorNBW() { @@ -59,22 +64,20 @@ public: delete[] data; } - bool *data; - - void reserve(const int &sz) + void reserve(size_t sz) { if (sz <= datareserve) return; bool *newdataLoc = new bool[sz]; if (datasize != 0) - memcpy(newdataLoc, data, sizeof(datasize)); + memcpy(newdataLoc, data, sizeof(bool) * sizeof(datasize)); std::swap(data, newdataLoc); if (newdataLoc != 0) delete[] newdataLoc; datareserve = sz; } - void resize(const int &sz) + void resize(size_t sz) { int oldDatasize = datasize; if (sz <= oldDatasize) @@ -96,14 +99,16 @@ public: bool empty() const { return datasize == 0; } - bool *begin() const { return data; } + bool* begin() {return data;} + const bool *begin() const { return data; } - bool &operator[](const int &i) { return data[i]; } - const bool &operator[](const int &i) const { return data[i]; } + bool &operator[](size_t i) { return data[i]; } + const bool &operator[](size_t i) const { return data[i]; } private: - int datasize; - int datareserve; + bool *data; + size_t datasize; + size_t datareserve; }; template From 3bfe5793f6145aa5ec6efcb583641247b7d81c57 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 23 Mar 2021 13:15:24 +0100 Subject: [PATCH 082/140] SimpleTempData DataBegin and const DataBegin --- vcg/complex/allocate.h | 4 ++-- vcg/complex/base.h | 2 +- vcg/container/simple_temporary_data.h | 34 +++++++++++++++------------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index fb088206..c81368ba 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -2207,7 +2207,7 @@ public: pa._padding = 0; } - template + template static void FixPaddedPerTetraAttribute(MeshType &m, PointerToAttribute &pa) { @@ -2245,7 +2245,7 @@ public: // copy the padded container in the new one char * ptr = (char*)( ((Attribute *)pa._handle)->DataBegin()); - memcpy((void*)_handle->attribute ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE)); + memcpy((void*)_handle->DataBegin() ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE)); // remove the padded container delete ( (Attribute *) pa._handle); diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 828bdcae..599cc975 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -340,7 +340,7 @@ public: Attribute * _handle; int n_attr; - ATTR_TYPE & operator ()(){ return *((Attribute *)_handle)->attribute;} + ATTR_TYPE & operator ()(){ return *((ATTR_TYPE*)((Attribute *)_handle)->DataBegin());} }; // Some common Handle typedefs to simplify use diff --git a/vcg/container/simple_temporary_data.h b/vcg/container/simple_temporary_data.h index 059d65c7..ac00c378 100644 --- a/vcg/container/simple_temporary_data.h +++ b/vcg/container/simple_temporary_data.h @@ -41,6 +41,7 @@ public: virtual void Reorder(std::vector &newVertIndex) = 0; virtual size_t SizeOf() const = 0; virtual void *DataBegin() = 0; + virtual const void* DataBegin() const = 0; virtual void *At(size_t i) = 0; virtual const void *At(size_t i) const = 0; @@ -56,12 +57,12 @@ template class VectorNBW { public: - VectorNBW() : data(nullptr), datasize(0), datareserve(0) {} + VectorNBW() : booldata(nullptr), datasize(0), datareserve(0) {} ~VectorNBW() { - if (data) - delete[] data; + if (booldata) + delete[] booldata; } void reserve(size_t sz) @@ -70,8 +71,8 @@ public: return; bool *newdataLoc = new bool[sz]; if (datasize != 0) - memcpy(newdataLoc, data, sizeof(bool) * sizeof(datasize)); - std::swap(data, newdataLoc); + memcpy(newdataLoc, booldata, sizeof(bool) * sizeof(datasize)); + std::swap(booldata, newdataLoc); if (newdataLoc != 0) delete[] newdataLoc; datareserve = sz; @@ -85,12 +86,12 @@ public: if (sz > datareserve) reserve(sz); datasize = sz; - memset(&data[oldDatasize], 0, datasize - oldDatasize); + memset(&booldata[oldDatasize], 0, datasize - oldDatasize); } void push_back(const bool &v) { resize(datasize + 1); - data[datasize] = v; + booldata[datasize] = v; } void clear() { datasize = 0; } @@ -99,14 +100,14 @@ public: bool empty() const { return datasize == 0; } - bool* begin() {return data;} - const bool *begin() const { return data; } + bool* data() {return booldata;} + const bool *data() const { return booldata; } - bool &operator[](size_t i) { return data[i]; } - const bool &operator[](size_t i) const { return data[i]; } + bool &operator[](size_t i) { return booldata[i]; } + const bool &operator[](size_t i) const { return booldata[i]; } private: - bool *data; + bool *booldata; size_t datasize; size_t datareserve; }; @@ -184,7 +185,7 @@ public: void Reorder(std::vector &newVertIndex) { - for (unsigned int i = 0; i < data.size(); ++i) + for (size_t i = 0; i < data.size(); ++i) { if (newVertIndex[i] != (std::numeric_limits::max)()) data[newVertIndex[i]] = data[i]; @@ -192,7 +193,8 @@ public: } size_t SizeOf() const { return sizeof(ATTR_TYPE); } - void *DataBegin() { return data.empty() ? NULL : &(*data.begin()); } + void *DataBegin() { return data.empty() ? nullptr : data.data(); } + const void *DataBegin() const { return data.empty() ? nullptr : data.data(); } }; template @@ -200,11 +202,11 @@ class Attribute : public SimpleTempDataBase { public: typedef ATTR_TYPE AttrType; - AttrType *attribute; Attribute() { attribute = new ATTR_TYPE(); } ~Attribute() { delete attribute; } size_t SizeOf() const { return sizeof(ATTR_TYPE); } void *DataBegin() { return attribute; } + const void* DataBegin() const {return attribute;} void Resize(size_t) { assert(0); } void Reorder(std::vector &) { assert(0); } @@ -220,6 +222,8 @@ public: return (void *)0; } void CopyValue(const size_t, const size_t, const SimpleTempDataBase *) { assert(0); } +private: + AttrType *attribute; }; } // end namespace vcg From 7c601cc83757963a11010345d4e2a538040777f3 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 23 Mar 2021 15:27:13 +0100 Subject: [PATCH 083/140] ConstPerVertexAttributeHandle --- vcg/complex/allocate.h | 39 +++++++++++++++++++++++------------- vcg/complex/base.h | 26 ++++++++++++++++++++++++ wrap/io_trimesh/export_ply.h | 28 +++++++++++++------------- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index c81368ba..3a6a6b85 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1434,6 +1434,17 @@ public: return false; } + /*! \brief Check if a const handle to a Per-Vertex Attribute is valid + */ + template + static + bool IsValidHandle( const MeshType & m, const typename MeshType::template ConstPerVertexAttributeHandle & a){ + if(a._handle == nullptr) return false; + for(AttrIterator i = m.vert_attr.begin(); i!=m.vert_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } + /*! \brief Add a Per-Vertex Attribute of the given ATTR_TYPE with the given name. No attribute with that name must exists (even of different type) @@ -1482,20 +1493,20 @@ public: } return AddPerVertexAttribute(m,name); } - - /*! \brief gives a handle to a per-vertex attribute with a given name and ATTR_TYPE + + /*! \brief gives a const handle to a per-vertex attribute with a given name and ATTR_TYPE \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. Otherwise, returns an invalid handle (check it using IsValidHandle). */ template static - typename MeshType::template PerVertexAttributeHandle - GetPerVertexAttribute( const MeshType & m, std::string name = std::string("")){ - typename MeshType::template PerVertexAttributeHandle h; + typename MeshType::template ConstPerVertexAttributeHandle + GetConstPerVertexAttribute( const MeshType & m, std::string name = std::string("")){ + typename MeshType::template ConstPerVertexAttributeHandle h; if(!name.empty()){ - return FindPerVertexAttribute(m,name); + return FindConstPerVertexAttribute(m,name); } - return typename MeshType:: template PerVertexAttributeHandle(nullptr,0); + return typename MeshType:: template ConstPerVertexAttributeHandle(nullptr,0); } /*! \brief Try to retrieve an handle to an attribute with a given name and ATTR_TYPE @@ -1524,15 +1535,15 @@ public: } return typename MeshType:: template PerVertexAttributeHandle(nullptr,0); } - + /** * Same as the one above, but without modifying the attribute if it is found. * (A "find" function should never modify the container in which is looking for..) * Input mesh is const. */ template - static typename MeshType::template PerVertexAttributeHandle - FindPerVertexAttribute( const MeshType & m, const std::string & name) + static typename MeshType::template ConstPerVertexAttributeHandle + FindConstPerVertexAttribute( const MeshType & m, const std::string & name) { assert(!name.empty()); PointerToAttribute h1; h1._name = name; @@ -1541,9 +1552,9 @@ public: i =m.vert_attr.find(h1); if(i!=m.vert_attr.end()) if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - return typename MeshType::template PerVertexAttributeHandle((*i)._handle,(*i).n_attr); + return typename MeshType::template ConstPerVertexAttributeHandle((*i)._handle,(*i).n_attr); } - return typename MeshType:: template PerVertexAttributeHandle(nullptr,0); + return typename MeshType:: template ConstPerVertexAttributeHandle(nullptr,0); } /*! \brief query the mesh for all the attributes per vertex @@ -1556,8 +1567,8 @@ public: for(i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i ) if(!(*i)._name.empty()) { - typename MeshType:: template PerVertexAttributeHandle hh; - hh = Allocator:: template FindPerVertexAttribute (m,(*i)._name); + typename MeshType:: template ConstPerVertexAttributeHandle hh; + hh = Allocator:: template FindConstPerVertexAttribute (m,(*i)._name); if(IsValidHandle(m,hh)) all.push_back((*i)._name); } diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 599cc975..678d715e 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -297,6 +297,25 @@ public: void resize(size_t /*size*/) { }; }; + template + class ConstAttributeHandle{ + public: + ConstAttributeHandle(){_handle=(SimpleTempData *)nullptr;} + ConstAttributeHandle( const void *ah,const int & n):_handle ( (const SimpleTempData *)ah ),n_attr(n){} + + + //pointer to the SimpleTempData that stores the attribute + const SimpleTempData * _handle; + + // its attribute number + int n_attr; + + // access function + template + const ATTR_TYPE & operator [](const RefType & i) const {return (*_handle)[i];} + void resize(size_t /*size*/) { }; + }; + template class PerVertexAttributeHandle: public AttributeHandle{ public: @@ -304,6 +323,13 @@ public: PerVertexAttributeHandle( void *ah,const int & n):AttributeHandle(ah,n){} }; + template + class ConstPerVertexAttributeHandle: public ConstAttributeHandle{ + public: + ConstPerVertexAttributeHandle():ConstAttributeHandle(){} + ConstPerVertexAttributeHandle( const void *ah,const int & n):ConstAttributeHandle(ah,n){} + }; + template class PerFaceAttributeHandle: public AttributeHandle{ diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index 05364d73..c871d8d2 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -93,7 +93,7 @@ namespace vcg { return Save(m,filename,binary,pi,cb); } - static int Save(const SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi, CallBackPos *cb=0) // V1.0 + static int Save(const SaveMeshType &m, const char * filename, bool binary, const PlyInfo &pi, CallBackPos *cb=0) // V1.0 { FILE * fpout; const char * hbin = "binary_little_endian"; @@ -112,7 +112,7 @@ namespace vcg { fpout = fopen(filename,"wb"); if(fpout==NULL) { - pi.status=::vcg::ply::E_CANTOPEN; + //pi.status=::vcg::ply::E_CANTOPEN; return ::vcg::ply::E_CANTOPEN; } fprintf(fpout, @@ -360,12 +360,12 @@ namespace vcg { VertexIterator vi; SimpleTempData indices(m.vert); - std::vector > thfv(pi.VertDescriptorVec.size()); - std::vector > thdv(pi.VertDescriptorVec.size()); - std::vector > thiv(pi.VertDescriptorVec.size()); - std::vector > thsv(pi.VertDescriptorVec.size()); - std::vector > thcv(pi.VertDescriptorVec.size()); - std::vector > thuv(pi.VertDescriptorVec.size()); + std::vector > thfv(pi.VertDescriptorVec.size()); + std::vector > thdv(pi.VertDescriptorVec.size()); + std::vector > thiv(pi.VertDescriptorVec.size()); + std::vector > thsv(pi.VertDescriptorVec.size()); + std::vector > thcv(pi.VertDescriptorVec.size()); + std::vector > thuv(pi.VertDescriptorVec.size()); for(size_t i=0;i::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_FLOAT : thfv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; default : assert(0); } } From e0ccec2fc8667658bb31dc6892844fc47cf0a5f1 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 23 Mar 2021 16:12:04 +0100 Subject: [PATCH 084/140] ConstPerFaceAttributeHandle --- vcg/complex/allocate.h | 99 +++++++++++++++++++++--------------- vcg/complex/base.h | 23 ++++++++- wrap/io_trimesh/export_ply.h | 24 ++++----- 3 files changed, 91 insertions(+), 55 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 3a6a6b85..b1bed546 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1423,8 +1423,9 @@ public: public: - /*! \brief Check if an handle to a Per-Vertex Attribute is valid - */ + /** + * @brief Checks if a handle to a Per-Vertex Attribute is valid + */ template static bool IsValidHandle( const MeshType & m, const typename MeshType::template PerVertexAttributeHandle & a){ @@ -1434,8 +1435,9 @@ public: return false; } - /*! \brief Check if a const handle to a Per-Vertex Attribute is valid - */ + /** + * @brief Checks if a const handle to a Per-Vertex Attribute is valid + */ template static bool IsValidHandle( const MeshType & m, const typename MeshType::template ConstPerVertexAttributeHandle & a){ @@ -1501,12 +1503,8 @@ public: template static typename MeshType::template ConstPerVertexAttributeHandle - GetConstPerVertexAttribute( const MeshType & m, std::string name = std::string("")){ - typename MeshType::template ConstPerVertexAttributeHandle h; - if(!name.empty()){ - return FindConstPerVertexAttribute(m,name); - } - return typename MeshType:: template ConstPerVertexAttributeHandle(nullptr,0); + GetPerVertexAttribute( const MeshType & m, std::string name = std::string("")){ + return FindPerVertexAttribute(m,name); } /*! \brief Try to retrieve an handle to an attribute with a given name and ATTR_TYPE @@ -1537,23 +1535,26 @@ public: } /** - * Same as the one above, but without modifying the attribute if it is found. - * (A "find" function should never modify the container in which is looking for..) - * Input mesh is const. + * @brief Try to retrieve a const handle to an attribute with a given name + * and ATTR_TYPE, from the given const mesh. + * If not found, an invalid handle will be returned. + * Check it with the function IsValidHandle */ template static typename MeshType::template ConstPerVertexAttributeHandle - FindConstPerVertexAttribute( const MeshType & m, const std::string & name) + FindPerVertexAttribute( const MeshType & m, const std::string & name) { - assert(!name.empty()); - PointerToAttribute h1; h1._name = name; - typename std::set :: iterator i; + if(!name.empty()){ + PointerToAttribute h1; h1._name = name; + typename std::set :: iterator i; - i =m.vert_attr.find(h1); - if(i!=m.vert_attr.end()) - if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - return typename MeshType::template ConstPerVertexAttributeHandle((*i)._handle,(*i).n_attr); + i =m.vert_attr.find(h1); + if(i!=m.vert_attr.end()){ + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + return typename MeshType::template ConstPerVertexAttributeHandle((*i)._handle,(*i).n_attr); + } } + } return typename MeshType:: template ConstPerVertexAttributeHandle(nullptr,0); } @@ -1568,7 +1569,7 @@ public: if(!(*i)._name.empty()) { typename MeshType:: template ConstPerVertexAttributeHandle hh; - hh = Allocator:: template FindConstPerVertexAttribute (m,(*i)._name); + hh = Allocator:: template FindPerVertexAttribute (m,(*i)._name); if(IsValidHandle(m,hh)) all.push_back((*i)._name); } @@ -1742,6 +1743,9 @@ public: } /// Per Face Attributes + /** + * @brief Checks if a handle to a Per-Face attribute is valid + */ template static bool IsValidHandle( const MeshType & m, const typename MeshType::template PerFaceAttributeHandle & a){ @@ -1751,6 +1755,18 @@ public: return false; } + /** + * @brief Checks if a const handle to a Per-Face attribute is valid + */ + template + static + bool IsValidHandle( const MeshType & m, const typename MeshType::template ConstPerFaceAttributeHandle & a){ + if(a._handle == nullptr) return false; + for(AttrIterator i = m.face_attr.begin(); i!=m.face_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } + template static typename MeshType::template PerFaceAttributeHandle @@ -1803,13 +1819,9 @@ public: */ template static - typename MeshType::template PerFaceAttributeHandle + typename MeshType::template ConstPerFaceAttributeHandle GetPerFaceAttribute( const MeshType & m, std::string name = std::string("")){ - typename MeshType::template PerFaceAttributeHandle h; - if(!name.empty()){ - return FindPerFaceAttribute(m,name); - } - return typename MeshType:: template PerFaceAttributeHandle(nullptr,0); + return FindPerFaceAttribute(m,name); } template @@ -1823,7 +1835,7 @@ public: i =m.face_attr.find(h1); if(i!=m.face_attr.end()) if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - if( (*i)._padding != 0 ){ + if( (*i)._padding != 0 ){ PointerToAttribute attr = (*i); // copy the PointerToAttribute m.face_attr.erase(i); // remove it from the set FixPaddedPerFaceAttribute(m,attr); @@ -1837,24 +1849,27 @@ public: } /** - * Same as the one above, but without modifying the attribute if it is found. - * (A "find" function should never modify the container in which is looking for..) - * Input mesh is const. + * @brief Try to retrieve a const handle to an attribute with a given name + * and ATTR_TYPE, from the given const mesh. + * If not found, an invalid handle will be returned. + * Check it with the function IsValidHandle */ template static - typename MeshType::template PerFaceAttributeHandle + typename MeshType::template ConstPerFaceAttributeHandle FindPerFaceAttribute( const MeshType & m, const std::string & name){ - assert(!name.empty()); - PointerToAttribute h1; h1._name = name; - typename std::set ::iterator i; + if(!name.empty()){ + PointerToAttribute h1; h1._name = name; + typename std::set ::iterator i; - i =m.face_attr.find(h1); - if(i!=m.face_attr.end()) - if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - return typename MeshType::template PerFaceAttributeHandle((*i)._handle,(*i).n_attr); + i =m.face_attr.find(h1); + if(i!=m.face_attr.end()){ + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + return typename MeshType::template ConstPerFaceAttributeHandle((*i)._handle,(*i).n_attr); + } } - return typename MeshType:: template PerFaceAttributeHandle(nullptr,0); + } + return typename MeshType:: template ConstPerFaceAttributeHandle(nullptr,0); } template @@ -1864,7 +1879,7 @@ public: for(i = m.face_attr.begin(); i != m.face_attr.end(); ++i ) if(!(*i)._name.empty()) { - typename MeshType:: template PerFaceAttributeHandle hh; + typename MeshType:: template ConstPerFaceAttributeHandle hh; hh = Allocator:: template FindPerFaceAttribute (m,(*i)._name); if(IsValidHandle(m,hh)) all.push_back((*i)._name); diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 678d715e..2afd27a1 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -330,7 +330,6 @@ public: ConstPerVertexAttributeHandle( const void *ah,const int & n):ConstAttributeHandle(ah,n){} }; - template class PerFaceAttributeHandle: public AttributeHandle{ public: @@ -338,6 +337,13 @@ public: PerFaceAttributeHandle( void *ah,const int & n):AttributeHandle(ah,n){} }; + template + class ConstPerFaceAttributeHandle: public ConstAttributeHandle{ + public: + ConstPerFaceAttributeHandle():ConstAttributeHandle(){} + ConstPerFaceAttributeHandle( void *ah,const int & n):ConstAttributeHandle(ah,n){} + }; + template class PerEdgeAttributeHandle: public AttributeHandle{ public: @@ -345,6 +351,13 @@ public: PerEdgeAttributeHandle( void *ah,const int & n):AttributeHandle(ah,n){} }; + template + class ConstPerEdgeAttributeHandle: public ConstAttributeHandle{ + public: + ConstPerEdgeAttributeHandle():ConstAttributeHandle(){} + ConstPerEdgeAttributeHandle( void *ah,const int & n):ConstAttributeHandle(ah,n){} + }; + template class PerTetraAttributeHandle : public AttributeHandle { @@ -353,6 +366,14 @@ public: PerTetraAttributeHandle(void *ah, const int &n) : AttributeHandle(ah, n) {} }; + template + class ConstPerTetraAttributeHandle : public ConstAttributeHandle + { + public: + ConstPerTetraAttributeHandle() : ConstAttributeHandle() {} + ConstPerTetraAttributeHandle(void *ah, const int &n) : ConstAttributeHandle(ah, n) {} + }; + template class PerMeshAttributeHandle{ public: diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index c871d8d2..d2c9d3cf 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -374,22 +374,22 @@ namespace vcg { assert(vcg::tri::HasPerVertexAttribute(m,pi.VertAttrNameVec[i])); switch (pi.VertDescriptorVec[i].stotype1) { - case ply::T_FLOAT : thfv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindConstPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_FLOAT : thfv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; default : assert(0); } } } - std::vector > thff(pi.FaceDescriptorVec.size()); - std::vector > thdf(pi.FaceDescriptorVec.size()); - std::vector > thif(pi.FaceDescriptorVec.size()); - std::vector > thsf(pi.FaceDescriptorVec.size()); - std::vector > thcf(pi.FaceDescriptorVec.size()); - std::vector > thuf(pi.FaceDescriptorVec.size()); + std::vector > thff(pi.FaceDescriptorVec.size()); + std::vector > thdf(pi.FaceDescriptorVec.size()); + std::vector > thif(pi.FaceDescriptorVec.size()); + std::vector > thsf(pi.FaceDescriptorVec.size()); + std::vector > thcf(pi.FaceDescriptorVec.size()); + std::vector > thuf(pi.FaceDescriptorVec.size()); for(size_t i=0;i Date: Tue, 23 Mar 2021 16:20:31 +0100 Subject: [PATCH 085/140] ConstPerEdgeAttributeHandle --- vcg/complex/allocate.h | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index b1bed546..f185d83f 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1628,6 +1628,15 @@ public: return false; } + template + static + bool IsValidHandle( const MeshType & m, const typename MeshType::template ConstPerEdgeAttributeHandle & a){ + if(a._handle == nullptr) return false; + for(AttrIterator i = m.edge_attr.begin(); i!=m.edge_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } + template static typename MeshType::template PerEdgeAttributeHandle @@ -1674,6 +1683,12 @@ public: return AddPerEdgeAttribute(m,name); } + template + static + typename MeshType::template ConstPerEdgeAttributeHandle + GetPerEdgeAttribute( const MeshType & m, std::string name = std::string("")){ + return FindPerEdgeAttribute(m,name); + } template static @@ -1700,6 +1715,24 @@ public: return typename MeshType:: template PerEdgeAttributeHandle(nullptr,0); } + template + static + typename MeshType::template ConstPerEdgeAttributeHandle + FindPerEdgeAttribute( const MeshType & m, const std::string & name){ + if(!name.empty()){ + PointerToAttribute h1; h1._name = name; + typename std::set ::const_iterator i; + + i =m.edge_attr.find(h1); + if(i!=m.edge_attr.end()){ + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + return typename MeshType::template ConstPerEdgeAttributeHandle((*i)._handle,(*i).n_attr); + } + } + } + return typename MeshType:: template ConstPerEdgeAttributeHandle(nullptr,0); + } + template static void GetAllPerEdgeAttribute(const MeshType & m, std::vector &all){ all.clear(); @@ -1707,7 +1740,7 @@ public: for(i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i ) if(!(*i)._name.empty()) { - typename MeshType:: template PerEdgeAttributeHandle hh; + typename MeshType:: template ConstPerEdgeAttributeHandle hh; hh = Allocator:: template FindPerEdgeAttribute (m,(*i)._name); if(IsValidHandle(m,hh)) all.push_back((*i)._name); From 94dc161edb8471026ac11f156db566501cc0ad8f Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 23 Mar 2021 16:30:36 +0100 Subject: [PATCH 086/140] ConstPerTetraAttributeHandle --- vcg/complex/allocate.h | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index f185d83f..170ac390 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1957,6 +1957,17 @@ public: return false; } + template + static bool IsValidHandle(const MeshType & m, const typename MeshType::template ConstPerTetraAttributeHandle & a) + { + if (a._handle == nullptr) + return false; + for (AttrIterator i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i) + if ((*i).n_attr == a.n_attr) + return true; + return false; + } + template static typename MeshType::template PerTetraAttributeHandle AddPerTetraAttribute(MeshType & m, std::string name) { @@ -2002,6 +2013,12 @@ public: return AddPerTetraAttribute(m, name); } + template + static typename MeshType::template ConstPerTetraAttributeHandle GetPerTetraAttribute(const MeshType &m, std::string name = std::string("")) + { + return FindPerTetraAttribute(m, name); + } + template static typename MeshType::template PerTetraAttributeHandle FindPerTetraAttribute(MeshType &m, const std::string &name) { @@ -2029,14 +2046,33 @@ public: } template - static void GetAllPerTetraAttribute(MeshType &m, std::vector &all) + static typename MeshType::template ConstPerTetraAttributeHandle FindPerTetraAttribute(MeshType &m, const std::string &name) + { + if(!name.empty()){ + PointerToAttribute h1; + h1._name = name; + typename std::set::iterator i; + + i = m.tetra_attr.find(h1); + if (i != m.tetra_attr.end()){ + if ((*i)._sizeof == sizeof(ATTR_TYPE)) + { + return typename MeshType::template ConstPerTetraAttributeHandle((*i)._handle, (*i).n_attr); + } + } + } + return typename MeshType::template ConstPerTetraAttributeHandle(nullptr, 0); + } + + template + static void GetAllPerTetraAttribute(const MeshType &m, std::vector &all) { all.clear(); typename std::set::const_iterator i; for (i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i) if (!(*i)._name.empty()) { - typename MeshType::template PerTetraAttributeHandle hh; + typename MeshType::template ConstPerTetraAttributeHandle hh; hh = Allocator::template FindPerTetraAttribute(m, (*i)._name); if (IsValidHandle(m, hh)) all.push_back((*i)._name); From 34af1c91bd76d8b81a3db6dc500b9b297a113f83 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 23 Mar 2021 16:52:56 +0100 Subject: [PATCH 087/140] ConstPerMeshAttributeHandle --- vcg/complex/allocate.h | 34 ++++++++++++++++++++++++++++++++++ vcg/complex/base.h | 13 ++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 170ac390..fa56dd27 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -2121,6 +2121,15 @@ public: return false; } + template + static + bool IsValidHandle(const MeshType & m, const typename MeshType::template ConstPerMeshAttributeHandle & a){ + if(a._handle == nullptr) return false; + for(AttrIterator i = m.mesh_attr.begin(); i!=m.mesh_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } + template static typename MeshType::template PerMeshAttributeHandle @@ -2159,6 +2168,13 @@ public: return AddPerMeshAttribute(m,name); } + template + static + typename MeshType::template ConstPerMeshAttributeHandle + GetPerMeshAttribute(const MeshType & m, std::string name = std::string("")){ + return FindPerMeshAttribute(m,name); + } + template static typename MeshType::template PerMeshAttributeHandle @@ -2185,6 +2201,24 @@ public: return typename MeshType:: template PerMeshAttributeHandle(nullptr,0); } + template + static + typename MeshType::template ConstPerMeshAttributeHandle + FindPerMeshAttribute( const MeshType & m, const std::string & name){ + if (!name.empty()){ + PointerToAttribute h1; h1._name = name; + typename std::set ::iterator i; + i =m.mesh_attr.find(h1); + if(i!=m.mesh_attr.end()){ + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + return typename MeshType::template ConstPerMeshAttributeHandle((*i)._handle,(*i).n_attr); + } + } + } + + return typename MeshType:: template ConstPerMeshAttributeHandle(nullptr,0); + } + template static void GetAllPerMeshAttribute(const MeshType & m, std::vector &all){ typename std::set :: iterator i; diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 2afd27a1..adb0316e 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -387,7 +387,18 @@ public: Attribute * _handle; int n_attr; - ATTR_TYPE & operator ()(){ return *((ATTR_TYPE*)((Attribute *)_handle)->DataBegin());} + ATTR_TYPE & operator ()(){ return *((ATTR_TYPE*) (_handle->DataBegin()));} + }; + + template + class ConstPerMeshAttributeHandle{ + public: + ConstPerMeshAttributeHandle(){_handle=nullptr;} + ConstPerMeshAttributeHandle(const void *ah,const int & n):_handle ( (const Attribute *)ah ),n_attr(n){} + + const Attribute * _handle; + int n_attr; + const ATTR_TYPE & operator ()(){ return *((const ATTR_TYPE*)(_handle->DataBegin()));} }; // Some common Handle typedefs to simplify use From ea276afef7233f4ae32af2cc0b30074853c98b23 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 23 Mar 2021 20:27:06 +0100 Subject: [PATCH 088/140] fix wrong static usage on PerElement PlyInfo --- wrap/io_trimesh/io_mask.h | 2 +- wrap/io_trimesh/io_ply.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wrap/io_trimesh/io_mask.h b/wrap/io_trimesh/io_mask.h index 8fa7d251..aafff054 100644 --- a/wrap/io_trimesh/io_mask.h +++ b/wrap/io_trimesh/io_mask.h @@ -66,7 +66,7 @@ public: enum { IOM_NONE = 0x00000, - IOM_VERTCOORD = 0x00001, + IOM_VERTCOORD = 0x00001, IOM_VERTFLAGS = 0x00002, IOM_VERTCOLOR = 0x00004, IOM_VERTQUALITY = 0x00008, diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index d0cfc042..5a504784 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -69,8 +69,8 @@ public: void AddPerElemFloatAttribute(int elemType, const char *attrName, const char * propName=0) { static const char *elemStr[2]={"vertex","face"}; - static std::vector *elemDescVec[2]={&(this->VertDescriptorVec), &(this->FaceDescriptorVec)}; - static std::vector *elemNameVec[2]={&(this->VertAttrNameVec), &(this->FaceAttrNameVec)}; + std::vector *elemDescVec[2]={&(this->VertDescriptorVec), &(this->FaceDescriptorVec)}; + std::vector *elemNameVec[2]={&(this->VertAttrNameVec), &(this->FaceAttrNameVec)}; if(propName==0) propName=attrName; elemDescVec[elemType]->push_back(PropDescriptor()); From 7efd90dc06e29b4a6066f29b4d3f168ae6c68e12 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 12:21:59 +0100 Subject: [PATCH 089/140] cmake configuration for vcglib --- CMakeLists.txt | 296 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..22083582 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,296 @@ +# Copyright 2019, 2020, Collabora, Ltd. +# Copyright 2019, 2021, Visual Computing Lab, ISTI - Italian National Research Council +# SPDX-License-Identifier: BSL-1.0 + +cmake_minimum_required(VERSION 3.13) +project(VCGLib) + +# Eigen options +option(ALLOW_BUNDLED_EIGEN "Allow use of bundled Eigen source" ON) +option(ALLOW_SYSTEM_EIGEN "Allow use of system-provided Eigen" ON) + +# VCG options +option(VCG_HEADER_ONLY "Use VCG library in header only mode" ON) +option(VCG_BUILD_EXAMPLES "Build a set of examples of the library" OFF) + +# Prefer GLVND +if(POLICY CMP0072) + cmake_policy(SET CMP0072 NEW) +endif() + +### Build settings +set(CMAKE_CXX_STANDARD 11) + +### Eigen +set(VCG_EIGEN_DIR ${CMAKE_CURRENT_LIST_DIR}/eigenlib) + +if(ALLOW_SYSTEM_EIGEN AND EIGEN3_INCLUDE_DIR) + message(STATUS "- Eigen - using system-provided library") + set(EIGEN_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR}) +elseif(ALLOW_BUNDLED_EIGEN AND EXISTS "${VCG_EIGEN_DIR}/Eigen/Eigen") + message(STATUS "- Eigen - using bundled source") + set(EIGEN_INCLUDE_DIRS ${VCG_EIGEN_DIR}) +else() + message( + FATAL_ERROR + "Eigen is required - at least one of ALLOW_SYSTEM_EIGEN or ALLOW_BUNDLED_EIGEN must be enabled and found.") +endif() + +### VCGLib headers and sources + +set(VCG_HEADERS + vcg/complex/append.h + vcg/complex/all_types.h + vcg/complex/complex.h + vcg/complex/allocate.h + vcg/complex/exception.h + vcg/complex/algorithms/overlap_estimation.h + vcg/complex/algorithms/dual_meshing.h + vcg/complex/algorithms/intersection.h + vcg/complex/algorithms/clip.h + vcg/complex/algorithms/geodesic.h + vcg/complex/algorithms/parametrization/poisson_solver.h + vcg/complex/algorithms/parametrization/uv_utils.h + vcg/complex/algorithms/parametrization/distortion.h + vcg/complex/algorithms/parametrization/tangent_field_operators.h + vcg/complex/algorithms/parametrization/voronoi_atlas.h + vcg/complex/algorithms/edge_collapse.h + vcg/complex/algorithms/hole.h + vcg/complex/algorithms/align_pair.h + vcg/complex/algorithms/closest.h + vcg/complex/algorithms/tetra_implicit_smooth.h + vcg/complex/algorithms/bitquad_support.h + vcg/complex/algorithms/skeleton.h + vcg/complex/algorithms/symmetry.h + vcg/complex/algorithms/voronoi_volume_sampling.h + vcg/complex/algorithms/polygon_polychord_collapse.h + vcg/complex/algorithms/inside.h + vcg/complex/algorithms/local_optimization/tri_edge_flip.h + vcg/complex/algorithms/local_optimization/quad_diag_collapse.h + vcg/complex/algorithms/local_optimization/tri_edge_collapse_quadric.h + vcg/complex/algorithms/local_optimization/tri_edge_collapse_quadric_tex.h + vcg/complex/algorithms/local_optimization/tri_edge_collapse.h + vcg/complex/algorithms/local_optimization/tetra_edge_collapse.h + vcg/complex/algorithms/polygonal_algorithms.h + vcg/complex/algorithms/inertia.h + vcg/complex/algorithms/mesh_assert.h + vcg/complex/algorithms/cut_tree.h + vcg/complex/algorithms/nring.h + vcg/complex/algorithms/tetra/tetfuse_collapse.h + vcg/complex/algorithms/stat.h + vcg/complex/algorithms/ransac_matching.h + vcg/complex/algorithms/refine.h + vcg/complex/algorithms/outline_support.h + vcg/complex/algorithms/convex_hull.h + vcg/complex/algorithms/clean.h + vcg/complex/algorithms/mesh_to_matrix.h + vcg/complex/algorithms/quadrangulator.h + vcg/complex/algorithms/isotropic_remeshing.h + vcg/complex/algorithms/smooth.h + vcg/complex/algorithms/autoalign_4pcs.h + vcg/complex/algorithms/local_optimization.h + vcg/complex/algorithms/curve_on_manifold.h + vcg/complex/algorithms/clustering.h + vcg/complex/algorithms/refine_loop.h + vcg/complex/algorithms/cylinder_clipping.h + vcg/complex/algorithms/pointcloud_normal.h + vcg/complex/algorithms/bitquad_creation.h + vcg/complex/algorithms/crease_cut.h + vcg/complex/algorithms/implicit_smooth.h + vcg/complex/algorithms/voronoi_remesher.h + vcg/complex/algorithms/polygon_support.h + vcg/complex/algorithms/point_sampling.h + vcg/complex/algorithms/create/mc_lookup_table.h + vcg/complex/algorithms/create/mc_trivial_walker.h + vcg/complex/algorithms/create/extrude.h + vcg/complex/algorithms/create/resampler.h + vcg/complex/algorithms/create/ball_pivoting.h + vcg/complex/algorithms/create/readme.txt + vcg/complex/algorithms/create/zonohedron.h + vcg/complex/algorithms/create/platonic.h + vcg/complex/algorithms/create/marching_cubes.h + vcg/complex/algorithms/create/plymc/voxel.h + vcg/complex/algorithms/create/plymc/simplemeshprovider.h + vcg/complex/algorithms/create/plymc/tri_edge_collapse_mc.h + vcg/complex/algorithms/create/plymc/volume.h + vcg/complex/algorithms/create/plymc/plymc.h + vcg/complex/algorithms/create/plymc/svoxel.h + vcg/complex/algorithms/create/tetramesh_support.h + vcg/complex/algorithms/create/advancing_front.h + vcg/complex/algorithms/textcoord_optimization.h + vcg/complex/algorithms/bitquad_optimization.h + vcg/complex/algorithms/halfedge_quad_clean.h + vcg/complex/algorithms/voronoi_processing.h + vcg/complex/algorithms/update/quality.h + vcg/complex/algorithms/update/selection.h + vcg/complex/algorithms/update/fitmaps.h + vcg/complex/algorithms/update/component_ep.h + vcg/complex/algorithms/update/texture.h + vcg/complex/algorithms/update/curvature_fitting.h + vcg/complex/algorithms/update/normal.h + vcg/complex/algorithms/update/position.h + vcg/complex/algorithms/update/halfedge_topology.h + vcg/complex/algorithms/update/topology.h + vcg/complex/algorithms/update/flag.h + vcg/complex/algorithms/update/bounding.h + vcg/complex/algorithms/update/halfedge_indexed.h + vcg/complex/algorithms/update/color.h + vcg/complex/algorithms/update/curvature.h + vcg/complex/algorithms/point_outlier.h + vcg/complex/algorithms/harmonic.h + vcg/complex/algorithms/point_matching_scale.h + vcg/complex/algorithms/attribute_seam.h + vcg/complex/foreach.h + vcg/complex/base.h + vcg/complex/used_types.h + vcg/container/entries_allocation_table.h + vcg/container/container_allocation_table.h + vcg/container/derivation_chain.h + vcg/container/vector_occ.h + vcg/container/simple_temporary_data.h + vcg/space/segment2.h + vcg/space/fitting3.h + vcg/space/tetra3.h + vcg/space/triangle2.h + vcg/space/ray2.h + vcg/space/deprecated_point2.h + vcg/space/point4.h + vcg/space/box2.h + vcg/space/ray3.h + vcg/space/planar_polygon_tessellation.h + vcg/space/texcoord2.h + vcg/space/deprecated_point3.h + vcg/space/intersection/triangle_triangle3.h + vcg/space/distance2.h + vcg/space/point3.h + vcg/space/deprecated_point.h + vcg/space/space.h + vcg/space/point.h + vcg/space/colorspace.h + vcg/space/rect_packer.h + vcg/space/triangle3.h + vcg/space/obox3.h + vcg/space/point2.h + vcg/space/smallest_enclosing.h + vcg/space/color4.h + vcg/space/polygon3.h + vcg/space/line3.h + vcg/space/index/octree.h + vcg/space/index/grid_util2d.h + vcg/space/index/grid_closest.h + vcg/space/index/grid_static_ptr.h + vcg/space/index/grid_util.h + vcg/space/index/spatial_hashing.h + vcg/space/index/closest2d.h + vcg/space/index/grid_static_obj.h + vcg/space/index/kdtree/kdtree.h + vcg/space/index/kdtree/priorityqueue.h + vcg/space/index/kdtree/kdtree_face.h + vcg/space/index/kdtree/mlsutils.h + vcg/space/index/octree_template.h + vcg/space/index/aabb_binary_tree/kclosest.h + vcg/space/index/aabb_binary_tree/closest.h + vcg/space/index/aabb_binary_tree/ray.h + vcg/space/index/aabb_binary_tree/frustum_cull.h + vcg/space/index/aabb_binary_tree/aabb_binary_tree.h + vcg/space/index/aabb_binary_tree/base.h + vcg/space/index/grid_closest2d.h + vcg/space/index/spatial_hashing2d.h + vcg/space/index/space_iterators.h + vcg/space/index/grid_static_ptr2d.h + vcg/space/index/base2d.h + vcg/space/index/base.h + vcg/space/index/perfect_spatial_hashing.h + vcg/space/index/space_iterators2d.h + vcg/space/line2.h + vcg/space/point_matching.h + vcg/space/intersection3.h + vcg/space/deprecated_point4.h + vcg/space/rasterized_outline2_packer.h + vcg/space/box.h + vcg/space/plane3.h + vcg/space/outline2_packer.h + vcg/space/segment3.h + vcg/space/intersection2.h + vcg/space/sphere3.h + vcg/space/box3.h + vcg/space/distance3.h + vcg/math/quadric5.h + vcg/math/factorial.h + vcg/math/eigen_matrix_addons.h + vcg/math/quadric.h + vcg/math/perlin_noise.h + vcg/math/shot.h + vcg/math/spherical_harmonics.h + vcg/math/eigen_matrixbase_addons.h + vcg/math/quaternion.h + vcg/math/similarity.h + vcg/math/disjoint_set.h + vcg/math/random_generator.h + vcg/math/camera.h + vcg/math/linear.h + vcg/math/matrix44.h + vcg/math/eigen.h + vcg/math/old_lin_algebra.h + vcg/math/similarity2.h + vcg/math/gen_normal.h + vcg/math/old_matrix44.h + vcg/math/old_deprecated_matrix.h + vcg/math/old_matrix33.h + vcg/math/polar_decomposition.h + vcg/math/base.h + vcg/math/histogram.h + vcg/math/legendre.h + vcg/math/matrix33.h + vcg/math/old_matrix.h + vcg/simplex/edge/distance.h + vcg/simplex/edge/topology.h + vcg/simplex/edge/pos.h + vcg/simplex/edge/component.h + vcg/simplex/edge/base.h + vcg/simplex/tetrahedron/tetrahedron.h + vcg/simplex/tetrahedron/topology.h + vcg/simplex/tetrahedron/pos.h + vcg/simplex/tetrahedron/component.h + vcg/simplex/tetrahedron/base.h + vcg/simplex/face/component_occ.h + vcg/simplex/face/component_ep.h + vcg/simplex/face/jumping_pos.h + vcg/simplex/face/distance.h + vcg/simplex/face/component_polygon.h + vcg/simplex/face/topology.h + vcg/simplex/face/pos.h + vcg/simplex/face/component.h + vcg/simplex/face/component_ocf.h + vcg/simplex/face/base.h + vcg/simplex/vertex/component_occ.h + vcg/simplex/vertex/component_sph.h + vcg/simplex/vertex/distance.h + vcg/simplex/vertex/component.h + vcg/simplex/vertex/component_ocf.h + vcg/simplex/vertex/base.h + vcg/connectors/halfedge_pos.h + vcg/connectors/hedge.h + vcg/connectors/hedge_component.h +) + +set(SOURCES +) + +if (VCG_HEADER_ONLY) + add_library(vcglib INTERFACE) + target_include_directories( + vcglib INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${EIGEN_INCLUDE_DIRS}) + + #just to show headers in ide + add_custom_target(vcglib_ide SOURCES ${VCG_HEADERS}) +else() + #TODO make vcglib that includes all the wrap sources, checking everytime + # if the the required targets (e.g. qt, gl, glew...) exists +endif() + +if(VCG_BUILD_EXAMPLES) + #TODO make the list of samples to build +endif() From 2e635647c4b203229c35bd9888718bd52c5c53f8 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 14:52:06 +0100 Subject: [PATCH 090/140] add wrap/callback to cmake headers --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22083582..d4790194 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,6 +272,9 @@ set(VCG_HEADERS vcg/connectors/halfedge_pos.h vcg/connectors/hedge.h vcg/connectors/hedge_component.h + + #wrap + wrap/callback.h ) set(SOURCES From 0b99eaa7b2625ee36226548dfa6b9c1dd45475d3 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 14:53:00 +0100 Subject: [PATCH 091/140] first complex.h files made self-sufficient --- vcg/complex/allocate.h | 11 ++++++++--- vcg/complex/base.h | 11 ++++++++--- vcg/complex/exception.h | 3 +++ vcg/container/simple_temporary_data.h | 5 +++-- vcg/simplex/edge/pos.h | 2 ++ vcg/simplex/edge/topology.h | 3 +++ vcg/simplex/face/pos.h | 2 ++ vcg/simplex/face/topology.h | 2 +- 8 files changed, 30 insertions(+), 9 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index fa56dd27..461684a9 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -23,9 +23,14 @@ #ifndef __VCGLIB_TRIALLOCATOR #define __VCGLIB_TRIALLOCATOR -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +#include +#include + +#include "used_types.h" + +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif namespace vcg { namespace tri { diff --git a/vcg/complex/base.h b/vcg/complex/base.h index adb0316e..60cdb8cc 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -20,12 +20,17 @@ * for more details. * * * ****************************************************************************/ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif #ifndef __VCG_COMPLEX_BASE #define __VCG_COMPLEX_BASE +#include +#include + +#include "used_types.h" + namespace vcg { class PointerToAttribute diff --git a/vcg/complex/exception.h b/vcg/complex/exception.h index b42c4c37..36d5ef6d 100644 --- a/vcg/complex/exception.h +++ b/vcg/complex/exception.h @@ -23,6 +23,9 @@ #ifndef __VCG_EXCEPTION_H #define __VCG_EXCEPTION_H +#include +#include + namespace vcg { class MissingComponentException : public std::runtime_error diff --git a/vcg/container/simple_temporary_data.h b/vcg/container/simple_temporary_data.h index ac00c378..4e91c195 100644 --- a/vcg/container/simple_temporary_data.h +++ b/vcg/container/simple_temporary_data.h @@ -24,10 +24,11 @@ #ifndef __VCGLIB_SIMPLE__ #define __VCGLIB_SIMPLE__ -#include +#include +#include #include #include -#include +#include namespace vcg { diff --git a/vcg/simplex/edge/pos.h b/vcg/simplex/edge/pos.h index 2b278f53..cc455bc9 100644 --- a/vcg/simplex/edge/pos.h +++ b/vcg/simplex/edge/pos.h @@ -24,6 +24,8 @@ #ifndef __VCG_EDGE_POS #define __VCG_EDGE_POS +#include + namespace vcg { namespace edge { diff --git a/vcg/simplex/edge/topology.h b/vcg/simplex/edge/topology.h index 6156a96d..13904c05 100644 --- a/vcg/simplex/edge/topology.h +++ b/vcg/simplex/edge/topology.h @@ -24,6 +24,9 @@ #ifndef _VCG_EDGE_TOPOLOGY #define _VCG_EDGE_TOPOLOGY +#include +#include + namespace vcg { namespace edge { /** \addtogroup edge */ diff --git a/vcg/simplex/face/pos.h b/vcg/simplex/face/pos.h index bfc0103f..a20d4ac3 100644 --- a/vcg/simplex/face/pos.h +++ b/vcg/simplex/face/pos.h @@ -29,6 +29,8 @@ #ifndef __VCG_FACE_POS #define __VCG_FACE_POS +#include + namespace vcg { namespace face { diff --git a/vcg/simplex/face/topology.h b/vcg/simplex/face/topology.h index bd14e018..bb07cec7 100644 --- a/vcg/simplex/face/topology.h +++ b/vcg/simplex/face/topology.h @@ -24,7 +24,7 @@ #ifndef _VCG_FACE_TOPOLOGY #define _VCG_FACE_TOPOLOGY -#include +#include namespace vcg { namespace face { From 4f3162ece5110d1668e07efff739a26b7cfcd369 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 15:48:57 +0100 Subject: [PATCH 092/140] all included from used_types.h have been made self sufficient --- vcg/complex/used_types.h | 1 - vcg/connectors/hedge.h | 9 ++++++++- vcg/connectors/hedge_component.h | 5 ++++- vcg/simplex/edge/base.h | 16 +++++++++++++--- vcg/simplex/edge/component.h | 13 ++++++++++--- vcg/simplex/face/base.h | 20 ++++++++++++++------ vcg/simplex/face/component.h | 12 +++++++++--- vcg/simplex/face/component_ocf.h | 12 +++++++++--- vcg/simplex/face/component_polygon.h | 6 +++++- vcg/simplex/tetrahedron/base.h | 11 +++++++---- vcg/simplex/tetrahedron/component.h | 2 ++ vcg/simplex/vertex/base.h | 11 ++++++++--- vcg/simplex/vertex/component.h | 12 +++++++++--- vcg/simplex/vertex/component_ocf.h | 16 ++++++++++------ 14 files changed, 108 insertions(+), 38 deletions(-) diff --git a/vcg/complex/used_types.h b/vcg/complex/used_types.h index 04daf9bb..570dd1ce 100755 --- a/vcg/complex/used_types.h +++ b/vcg/complex/used_types.h @@ -23,7 +23,6 @@ #ifndef VCG_USED_TYPES_H #define VCG_USED_TYPES_H -#include #include #include #include diff --git a/vcg/connectors/hedge.h b/vcg/connectors/hedge.h index e0785681..48f72a33 100644 --- a/vcg/connectors/hedge.h +++ b/vcg/connectors/hedge.h @@ -20,11 +20,18 @@ * for more details. * * * ****************************************************************************/ -#include #ifndef __VCG_HEDGE_ #define __VCG_HEDGE_ +#include +#include + +#include +#include + +#include "hedge_component.h" + namespace vcg { /*------------------------------------------------------------------*/ diff --git a/vcg/connectors/hedge_component.h b/vcg/connectors/hedge_component.h index 8c48a8d9..12c441a8 100644 --- a/vcg/connectors/hedge_component.h +++ b/vcg/connectors/hedge_component.h @@ -20,11 +20,14 @@ * for more details. * * * ****************************************************************************/ -#include #ifndef __VCG_HEDGE_COMPONENT #define __VCG_HEDGE_COMPONENT +#include +#include +#include + namespace vcg { namespace hedge { /* diff --git a/vcg/simplex/edge/base.h b/vcg/simplex/edge/base.h index 472a635b..42309db1 100644 --- a/vcg/simplex/edge/base.h +++ b/vcg/simplex/edge/base.h @@ -20,11 +20,21 @@ * for more details. * * * ****************************************************************************/ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif #ifndef __VCG_EDGE_PLUS #define __VCG_EDGE_PLUS + +#include +#include +#include + +#include +#include + +#include "component.h" + namespace vcg { /*------------------------------------------------------------------*/ /* diff --git a/vcg/simplex/edge/component.h b/vcg/simplex/edge/component.h index 69d32765..9c44c073 100644 --- a/vcg/simplex/edge/component.h +++ b/vcg/simplex/edge/component.h @@ -20,12 +20,19 @@ * for more details. * * * ****************************************************************************/ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif #ifndef __VCG_EDGE_PLUS_COMPONENT #define __VCG_EDGE_PLUS_COMPONENT +#include +#include +#include + +#include + + namespace vcg { namespace edge { diff --git a/vcg/simplex/face/base.h b/vcg/simplex/face/base.h index e96e541d..8f208cbd 100644 --- a/vcg/simplex/face/base.h +++ b/vcg/simplex/face/base.h @@ -20,12 +20,20 @@ * for more details. * * * ****************************************************************************/ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif #ifndef __VCG_FACE_PLUS #define __VCG_FACE_PLUS +#include +#include + +#include +#include + +#include "component.h" + namespace vcg { /*------------------------------------------------------------------*/ @@ -163,16 +171,16 @@ public: /// select the Face void SetS() {this->Flags() |=SELECTED;} /// Un-select a Face - void ClearS() {this->Flags() &= ~SELECTED;} + void ClearS() {this->Flags() &= ~SELECTED;} /// select the Face void SetV() {this->Flags() |=VISITED;} /// Un-select a Face - void ClearV() {this->Flags() &= ~VISITED;} + void ClearV() {this->Flags() &= ~VISITED;} /// This function checks if the face is selected bool IsB(int i) const {return (this->cFlags() & (BORDER0<Flags() |=(BORDER0<Flags() |=(BORDER0<Flags() &= (~(BORDER0< +#include +#include + +#include +#include namespace vcg { namespace face { diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index 3f676006..919b1a55 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -22,9 +22,15 @@ ****************************************************************************/ #ifndef __VCG_FACE_PLUS_COMPONENT_OCF #define __VCG_FACE_PLUS_COMPONENT_OCF -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif + +#include +#include + +#include +#include namespace vcg { namespace face { diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index b17c2f85..0a7cdd04 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -24,6 +24,10 @@ #ifndef __VCG_POLYGON_COMPONENT #define __VCG_POLYGON_COMPONENT +#include +#include +#include + namespace vcg { namespace face { @@ -60,7 +64,7 @@ public: typedef typename T::VertexType::ScalarType ScalarType; typedef typename T::VertexType VertexType; - PFVAdj(){ _vpoly = NULL; } + PFVAdj(){ _vpoly = nullptr; } /* Note: the destructor will not be called in general because there are no virtual destructors. * Instead, the job of deallocating the memory will be done by the face allocator. * This destructor is only done for those who istance a face alone (outside a mesh) diff --git a/vcg/simplex/tetrahedron/base.h b/vcg/simplex/tetrahedron/base.h index b5e9bc71..d541503c 100644 --- a/vcg/simplex/tetrahedron/base.h +++ b/vcg/simplex/tetrahedron/base.h @@ -36,10 +36,13 @@ added #ifndef __VCG_TETRA_PLUS #define __VCG_TETRA_PLUS -//#include -//#include -//#include -//#include +#include +#include + +#include +#include + +#include "component.h" namespace vcg { diff --git a/vcg/simplex/tetrahedron/component.h b/vcg/simplex/tetrahedron/component.h index 7cd9781d..cb1a6e87 100644 --- a/vcg/simplex/tetrahedron/component.h +++ b/vcg/simplex/tetrahedron/component.h @@ -34,6 +34,8 @@ added #define __VCG_TETRAHEDRON_PLUS_COMPONENT #include + +#include #include namespace vcg { diff --git a/vcg/simplex/vertex/base.h b/vcg/simplex/vertex/base.h index 29ec6fb5..649546f1 100644 --- a/vcg/simplex/vertex/base.h +++ b/vcg/simplex/vertex/base.h @@ -20,12 +20,17 @@ * for more details. * * * ****************************************************************************/ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif #ifndef __VCG_VERTEX_PLUS #define __VCG_VERTEX_PLUS +#include +#include + +#include "component.h" + namespace vcg { diff --git a/vcg/simplex/vertex/component.h b/vcg/simplex/vertex/component.h index f4cab3c9..4a1396d8 100644 --- a/vcg/simplex/vertex/component.h +++ b/vcg/simplex/vertex/component.h @@ -20,12 +20,18 @@ * for more details. * * * ****************************************************************************/ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif #ifndef __VCG_VERTEX_PLUS_COMPONENT #define __VCG_VERTEX_PLUS_COMPONENT +#include +#include + +#include +#include + namespace vcg { namespace vertex { /** \addtogroup VertexComponentGroup diff --git a/vcg/simplex/vertex/component_ocf.h b/vcg/simplex/vertex/component_ocf.h index 35572cbc..919a3090 100644 --- a/vcg/simplex/vertex/component_ocf.h +++ b/vcg/simplex/vertex/component_ocf.h @@ -25,14 +25,18 @@ OCF = Optional Component Fast (hopefully) compare with OCC(Optional Component Compact) */ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif #ifndef __VCG_VERTEX_PLUS_COMPONENT_OCF #define __VCG_VERTEX_PLUS_COMPONENT_OCF -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif + +#include +#include + +#include +#include + namespace vcg { namespace vertex { From e36aa76fbdca6a8d30be8020f8a8483f8037a8fb Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 16:08:53 +0100 Subject: [PATCH 093/140] complex and simplex self-sufficient headers --- vcg/complex/algorithms/update/flag.h | 4 ++++ vcg/complex/allocate.h | 2 ++ vcg/complex/foreach.h | 8 +++++--- vcg/simplex/edge/topology.h | 3 +++ vcg/simplex/face/topology.h | 2 ++ vcg/simplex/tetrahedron/pos.h | 9 +++++++-- vcg/simplex/tetrahedron/topology.h | 2 ++ 7 files changed, 25 insertions(+), 5 deletions(-) diff --git a/vcg/complex/algorithms/update/flag.h b/vcg/complex/algorithms/update/flag.h index 2a7957c2..75c6860c 100644 --- a/vcg/complex/algorithms/update/flag.h +++ b/vcg/complex/algorithms/update/flag.h @@ -23,6 +23,10 @@ #ifndef __VCG_TRI_UPDATE_FLAGS #define __VCG_TRI_UPDATE_FLAGS +#include +#include +#include + namespace vcg { namespace tri { /// \ingroup trimesh diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 461684a9..60c370dc 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -26,6 +26,8 @@ #include #include +#include + #include "used_types.h" //#ifndef __VCG_MESH diff --git a/vcg/complex/foreach.h b/vcg/complex/foreach.h index a062e41c..58dc3d99 100644 --- a/vcg/complex/foreach.h +++ b/vcg/complex/foreach.h @@ -24,9 +24,11 @@ #ifndef VCG__FOREACH_H #define VCG__FOREACH_H -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +//#ifndef __VCG_MESH +//#error "This file should not be included alone. It is automatically included by complex.h" +//#endif + +#include namespace vcg { namespace tri { diff --git a/vcg/simplex/edge/topology.h b/vcg/simplex/edge/topology.h index 13904c05..b942c5a8 100644 --- a/vcg/simplex/edge/topology.h +++ b/vcg/simplex/edge/topology.h @@ -27,6 +27,9 @@ #include #include +#include "pos.h" +#include "component.h" + namespace vcg { namespace edge { /** \addtogroup edge */ diff --git a/vcg/simplex/face/topology.h b/vcg/simplex/face/topology.h index bb07cec7..7caa961a 100644 --- a/vcg/simplex/face/topology.h +++ b/vcg/simplex/face/topology.h @@ -24,6 +24,8 @@ #ifndef _VCG_FACE_TOPOLOGY #define _VCG_FACE_TOPOLOGY +#include "pos.h" + #include namespace vcg { diff --git a/vcg/simplex/tetrahedron/pos.h b/vcg/simplex/tetrahedron/pos.h index c9ed4629..d47348ce 100644 --- a/vcg/simplex/tetrahedron/pos.h +++ b/vcg/simplex/tetrahedron/pos.h @@ -30,6 +30,11 @@ #ifndef __VCG_TETRA_POS #define __VCG_TETRA_POS +#include +#include + +#include "component.h" + namespace vcg { namespace tetra { @@ -87,7 +92,7 @@ public: return _vi; } - inline bool End(){return (Vt()==NULL);} + inline bool End(){return (Vt()==nullptr);} /// move on the next tetrahedron that share the vertex void operator++() @@ -97,7 +102,7 @@ public: Vt() = tw->VTp(vi); Vi() = tw->VTi(vi); - assert((Vt()==NULL)||((tw->V(vi))==(Vt()->V(Vi())))); + assert((Vt()==nullptr)||((tw->V(vi))==(Vt()->V(Vi())))); } }; diff --git a/vcg/simplex/tetrahedron/topology.h b/vcg/simplex/tetrahedron/topology.h index 5203af47..a72b8883 100644 --- a/vcg/simplex/tetrahedron/topology.h +++ b/vcg/simplex/tetrahedron/topology.h @@ -24,6 +24,8 @@ #ifndef _VCG_TETRA_TOPOLOGY #define _VCG_TETRA_TOPOLOGY +#include + namespace vcg { namespace tetrahedron { /** \addtogroup tetrahedron */ From 8408a1a1d1a98a4e6f004530fb9ecf16d84c4c72 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 17:47:49 +0100 Subject: [PATCH 094/140] all complex.h files are self-sufficient --- vcg/complex/algorithms/mesh_assert.h | 4 ++++ vcg/complex/algorithms/update/normal.h | 5 +++++ vcg/complex/algorithms/update/selection.h | 7 +++++++ vcg/complex/algorithms/update/topology.h | 6 ++++++ vcg/complex/append.h | 5 ++--- 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/vcg/complex/algorithms/mesh_assert.h b/vcg/complex/algorithms/mesh_assert.h index 5f8a174a..ec821a39 100644 --- a/vcg/complex/algorithms/mesh_assert.h +++ b/vcg/complex/algorithms/mesh_assert.h @@ -23,6 +23,10 @@ #ifndef __VCGLIB_MESH_ASSERT #define __VCGLIB_MESH_ASSERT +#include +#include +#include + namespace vcg { namespace tri { /** diff --git a/vcg/complex/algorithms/update/normal.h b/vcg/complex/algorithms/update/normal.h index cedd0434..e649e284 100644 --- a/vcg/complex/algorithms/update/normal.h +++ b/vcg/complex/algorithms/update/normal.h @@ -24,8 +24,13 @@ #ifndef __VCG_TRI_UPDATE_NORMALS #define __VCG_TRI_UPDATE_NORMALS +#include +#include + #include +#include "flag.h" + namespace vcg { namespace tri { diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index 221db704..48b90d22 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -23,6 +23,13 @@ #ifndef __VCG_TRI_UPDATE_SELECTION #define __VCG_TRI_UPDATE_SELECTION +#include + +#include +#include + +#include "flag.h" + namespace vcg { namespace tri { /// \ingroup trimesh diff --git a/vcg/complex/algorithms/update/topology.h b/vcg/complex/algorithms/update/topology.h index 3dcab7d6..a71f63e9 100644 --- a/vcg/complex/algorithms/update/topology.h +++ b/vcg/complex/algorithms/update/topology.h @@ -24,6 +24,12 @@ #ifndef __VCG_TRI_UPDATE_TOPOLOGY #define __VCG_TRI_UPDATE_TOPOLOGY +#include + +#include +#include +#include + namespace vcg { namespace tri { /// \ingroup trimesh diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 02580a4b..6be6826e 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -23,9 +23,8 @@ #ifndef __VCGLIB_APPEND #define __VCGLIB_APPEND -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif +#include +#include namespace vcg { namespace tri { From d69e3e67cc14970906a33efdd92894e24abb140e Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 17:59:53 +0100 Subject: [PATCH 095/140] cleanups --- vcg/complex/allocate.h | 4 ---- vcg/complex/base.h | 4 +--- vcg/complex/foreach.h | 4 ---- vcg/simplex/edge/base.h | 4 +--- vcg/simplex/edge/component.h | 4 +--- vcg/simplex/face/base.h | 4 +--- vcg/simplex/face/component.h | 4 +--- vcg/simplex/face/component_occ.h | 3 --- vcg/simplex/face/component_ocf.h | 3 --- vcg/simplex/tetrahedron/base.h | 4 +--- vcg/simplex/vertex/base.h | 4 +--- vcg/simplex/vertex/component.h | 4 +--- vcg/simplex/vertex/component_occ.h | 9 ++++++--- vcg/simplex/vertex/component_ocf.h | 4 +--- 14 files changed, 15 insertions(+), 44 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 60c370dc..b4b337d6 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -30,10 +30,6 @@ #include "used_types.h" -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif - namespace vcg { namespace tri { /** \addtogroup trimesh diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 60cdb8cc..4a1e01f9 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -20,9 +20,7 @@ * for more details. * * * ****************************************************************************/ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_COMPLEX_BASE #define __VCG_COMPLEX_BASE diff --git a/vcg/complex/foreach.h b/vcg/complex/foreach.h index 58dc3d99..c2fa2cef 100644 --- a/vcg/complex/foreach.h +++ b/vcg/complex/foreach.h @@ -24,10 +24,6 @@ #ifndef VCG__FOREACH_H #define VCG__FOREACH_H -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif - #include namespace vcg { diff --git a/vcg/simplex/edge/base.h b/vcg/simplex/edge/base.h index 42309db1..8f9a71b7 100644 --- a/vcg/simplex/edge/base.h +++ b/vcg/simplex/edge/base.h @@ -20,9 +20,7 @@ * for more details. * * * ****************************************************************************/ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_EDGE_PLUS #define __VCG_EDGE_PLUS diff --git a/vcg/simplex/edge/component.h b/vcg/simplex/edge/component.h index 9c44c073..4e922ae3 100644 --- a/vcg/simplex/edge/component.h +++ b/vcg/simplex/edge/component.h @@ -20,9 +20,7 @@ * for more details. * * * ****************************************************************************/ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_EDGE_PLUS_COMPONENT #define __VCG_EDGE_PLUS_COMPONENT diff --git a/vcg/simplex/face/base.h b/vcg/simplex/face/base.h index 8f208cbd..967c7dbc 100644 --- a/vcg/simplex/face/base.h +++ b/vcg/simplex/face/base.h @@ -20,9 +20,7 @@ * for more details. * * * ****************************************************************************/ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_FACE_PLUS #define __VCG_FACE_PLUS diff --git a/vcg/simplex/face/component.h b/vcg/simplex/face/component.h index 5337d687..5ac8b3d6 100644 --- a/vcg/simplex/face/component.h +++ b/vcg/simplex/face/component.h @@ -20,9 +20,7 @@ * for more details. * * * ****************************************************************************/ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_FACE_PLUS_COMPONENT #define __VCG_FACE_PLUS_COMPONENT diff --git a/vcg/simplex/face/component_occ.h b/vcg/simplex/face/component_occ.h index 318e5852..a9eb739a 100644 --- a/vcg/simplex/face/component_occ.h +++ b/vcg/simplex/face/component_occ.h @@ -26,9 +26,6 @@ OCC = Optional Component Compact compare with OCF(Optional Component Fast) */ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif #ifndef __VCG_FACE_PLUS_COMPONENT_OCC #define __VCG_FACE_PLUS_COMPONENT_OCC diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index 919b1a55..c0e0c0db 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -22,9 +22,6 @@ ****************************************************************************/ #ifndef __VCG_FACE_PLUS_COMPONENT_OCF #define __VCG_FACE_PLUS_COMPONENT_OCF -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif #include #include diff --git a/vcg/simplex/tetrahedron/base.h b/vcg/simplex/tetrahedron/base.h index d541503c..364cd857 100644 --- a/vcg/simplex/tetrahedron/base.h +++ b/vcg/simplex/tetrahedron/base.h @@ -30,9 +30,7 @@ added ****************************************************************************/ -// #ifndef __VCG_TETRA_MESH -// #error "This file should not be included alone. It is automatically included by complex.h" -// #endif + #ifndef __VCG_TETRA_PLUS #define __VCG_TETRA_PLUS diff --git a/vcg/simplex/vertex/base.h b/vcg/simplex/vertex/base.h index 649546f1..b12b0648 100644 --- a/vcg/simplex/vertex/base.h +++ b/vcg/simplex/vertex/base.h @@ -20,9 +20,7 @@ * for more details. * * * ****************************************************************************/ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_VERTEX_PLUS #define __VCG_VERTEX_PLUS diff --git a/vcg/simplex/vertex/component.h b/vcg/simplex/vertex/component.h index 4a1396d8..dab25640 100644 --- a/vcg/simplex/vertex/component.h +++ b/vcg/simplex/vertex/component.h @@ -20,9 +20,7 @@ * for more details. * * * ****************************************************************************/ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_VERTEX_PLUS_COMPONENT #define __VCG_VERTEX_PLUS_COMPONENT diff --git a/vcg/simplex/vertex/component_occ.h b/vcg/simplex/vertex/component_occ.h index 80e0e124..e15f5e68 100644 --- a/vcg/simplex/vertex/component_occ.h +++ b/vcg/simplex/vertex/component_occ.h @@ -33,12 +33,15 @@ Working release (compilata solo su MSVC), component_occ � migrato da component ****************************************************************************/ -#ifndef __VCG_MESH -#error "This file should not be included alone. It is automatically included by complex.h" -#endif + #ifndef __VCG_VERTEX_PLUS_COMPONENT_OCC #define __VCG_VERTEX_PLUS_COMPONENT_OCC +#include + +#include +#include + namespace vcg { namespace vertex { /* diff --git a/vcg/simplex/vertex/component_ocf.h b/vcg/simplex/vertex/component_ocf.h index 919a3090..c063308c 100644 --- a/vcg/simplex/vertex/component_ocf.h +++ b/vcg/simplex/vertex/component_ocf.h @@ -25,9 +25,7 @@ OCF = Optional Component Fast (hopefully) compare with OCC(Optional Component Compact) */ -//#ifndef __VCG_MESH -//#error "This file should not be included alone. It is automatically included by complex.h" -//#endif + #ifndef __VCG_VERTEX_PLUS_COMPONENT_OCF #define __VCG_VERTEX_PLUS_COMPONENT_OCF From adb799a0a2f6c51e407752add09eb8beddc18d58 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 24 Mar 2021 19:15:10 +0100 Subject: [PATCH 096/140] fix const correctnes of face/component.h --- vcg/complex/algorithms/harmonic.h | 8 +++--- vcg/complex/algorithms/isotropic_remeshing.h | 4 +-- vcg/simplex/face/component.h | 26 ++++++++++---------- vcg/simplex/face/pos.h | 26 ++++++++++++++++---- wrap/io_trimesh/export_3ds.h | 2 +- 5 files changed, 41 insertions(+), 25 deletions(-) diff --git a/vcg/complex/algorithms/harmonic.h b/vcg/complex/algorithms/harmonic.h index ec9a67cd..2c83d103 100644 --- a/vcg/complex/algorithms/harmonic.h +++ b/vcg/complex/algorithms/harmonic.h @@ -235,19 +235,19 @@ public: ScalarT cotB = 0; // Get the edge (a pair of vertices) - VertexType * v0 = f.cV(edge); - VertexType * v1 = f.cV((edge+1)%f.VN()); + const VertexType * v0 = f.cV(edge); + const VertexType * v1 = f.cV((edge+1)%f.VN()); if (fp != NULL && fp != &f) { // not a border edge - VertexType * vb = fp->cV((f.cFFi(edge)+2)%fp->VN()); + const VertexType * vb = fp->cV((f.cFFi(edge)+2)%fp->VN()); ScalarT angleB = ComputeAngle(v0, vb, v1); cotB = vcg::math::Cos(angleB) / vcg::math::Sin(angleB); } - VertexType * va = f.cV((edge+2)%f.VN()); + const VertexType * va = f.cV((edge+2)%f.VN()); ScalarT angleA = ComputeAngle(v0, va, v1); cotA = vcg::math::Cos(angleA) / vcg::math::Sin(angleA); diff --git a/vcg/complex/algorithms/isotropic_remeshing.h b/vcg/complex/algorithms/isotropic_remeshing.h index 264e7c08..5b7ac9ec 100644 --- a/vcg/complex/algorithms/isotropic_remeshing.h +++ b/vcg/complex/algorithms/isotropic_remeshing.h @@ -813,7 +813,7 @@ private: { if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+1)%3)) && !vcg::tri::IsMarked(*params.m, faces[i]->cV1(vIdxes[i]))) { - vcg::tri::Mark(*params.m,faces[i]->cV1(vIdxes[i])); + vcg::tri::Mark(*params.m,faces[i]->V1(vIdxes[i])); incidentFeatures++; CoordType movingEdgeVector0 = (faces[i]->cP1(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); if (std::fabs(movingEdgeVector0 * dEdgeVector) < .9f || !p.IsEdgeS()) @@ -821,7 +821,7 @@ private: } if (faces[i]->IsFaceEdgeS(VtoE(vIdxes[i], (vIdxes[i]+2)%3)) && !vcg::tri::IsMarked(*params.m, faces[i]->cV2(vIdxes[i]))) { - vcg::tri::Mark(*params.m,faces[i]->cV2(vIdxes[i])); + vcg::tri::Mark(*params.m,faces[i]->V2(vIdxes[i])); incidentFeatures++; CoordType movingEdgeVector1 = (faces[i]->cP2(vIdxes[i]) - faces[i]->cP(vIdxes[i])).Normalize(); if (std::fabs(movingEdgeVector1 * dEdgeVector) < .9f || !p.IsEdgeS()) diff --git a/vcg/simplex/face/component.h b/vcg/simplex/face/component.h index 5ac8b3d6..0ab89fb6 100644 --- a/vcg/simplex/face/component.h +++ b/vcg/simplex/face/component.h @@ -40,15 +40,15 @@ namespace face { template class EmptyCore: public T { public: - inline typename T::VertexType * &V( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } - inline typename T::VertexType * V( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } - inline typename T::VertexType * cV( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } - inline typename T::VertexType * &FVp( const int i ) { return this->V(i); } - inline typename T::VertexType * FVp( const int i ) const { return this->cV(i); } - inline typename T::VertexType * cFVp( const int i ) const { return this->cV(i); } - inline typename T::CoordType &P( const int ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } - inline typename T::CoordType P( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } - inline typename T::CoordType cP( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } + inline typename T::VertexType * &V( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } + inline const typename T::VertexType * V( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } + inline const typename T::VertexType * cV( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } + inline typename T::VertexType * &FVp( const int i ) { return this->V(i); } + inline const typename T::VertexType * FVp( const int i ) const { return this->cV(i); } + inline const typename T::VertexType * cFVp( const int i ) const { return this->cV(i); } + inline typename T::CoordType &P( const int ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } + inline typename T::CoordType P( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } + inline typename T::CoordType cP( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } static bool HasVertexRef() { return false; } static bool HasFVAdjacency() { return false; } @@ -200,7 +200,7 @@ public: inline typename T::VertexType * &V( const int j ) { assert(j>=0 && j<3); return v[j]; } /// \brief The pointer to the i-th vertex inline const typename T::VertexType * V (const int j) const { assert(j>=0 && j<3); return v[j]; } - inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && j<3); return v[j]; } + inline const typename T::VertexType * cV( const int j ) const { assert(j>=0 && j<3); return v[j]; } inline CoordType &P( const int j ) { assert(j>=0 && j<3); return v[j]->P(); } /// \brief Shortcut: the position of the i-th vertex (equivalent to \c V(i)->P() ) inline const CoordType &P( const int j ) const { assert(j>=0 && j<3); return v[j]->P(); } @@ -212,9 +212,9 @@ public: inline const typename T::VertexType * V0( const int j ) const { return V(j);} /** \brief Return the pointer to the j-th vertex of the face. */ inline const typename T::VertexType * V1( const int j ) const { return V((j+1)%3);} /** \brief Return the pointer to the ((j+1)%3)-th vertex of the face. */ inline const typename T::VertexType * V2( const int j ) const { return V((j+2)%3);} /** \brief Return the pointer to the ((j+2)%3)-th vertex of the face. */ - inline typename T::VertexType * cV0( const int j ) const { return cV(j);} - inline typename T::VertexType * cV1( const int j ) const { return cV((j+1)%3);} - inline typename T::VertexType * cV2( const int j ) const { return cV((j+2)%3);} + inline const typename T::VertexType * cV0( const int j ) const { return cV(j);} + inline const typename T::VertexType * cV1( const int j ) const { return cV((j+1)%3);} + inline const typename T::VertexType * cV2( const int j ) const { return cV((j+2)%3);} inline CoordType & P0( const int j ) { return V(j)->P();} inline CoordType & P1( const int j ) { return V((j+1)%3)->P();} diff --git a/vcg/simplex/face/pos.h b/vcg/simplex/face/pos.h index a20d4ac3..436226d1 100644 --- a/vcg/simplex/face/pos.h +++ b/vcg/simplex/face/pos.h @@ -219,15 +219,22 @@ public: } /// return the vertex that it should have if we make FlipV; - VertexType *VFlip() const + VertexType *VFlip() { - assert(f->cV(f->Prev(z))!=v && (f->cV(f->Next(z))==v || f->cV(z)==v)); - if(f->cV(f->Next(z))==v) return f->cV(z); - else return f->cV(f->Next(z)); + assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v)); + if(f->V(f->Next(z))==v) return f->V(z); + else return f->V(f->Next(z)); } + const VertexType *VFlip() const + { + assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v)); + if(f->V(f->Next(z))==v) return f->V(z); + else return f->V(f->Next(z)); + } + /// return the face that it should have if we make FlipF; - FaceType *FFlip() const + FaceType *FFlip() { // assert( f->FFp(z)->FFp(f->FFi(z))==f ); // assert(f->V(f->Prev(z))!=v); @@ -236,6 +243,15 @@ public: return nf; } + const FaceType *FFlip() const + { + // assert( f->FFp(z)->FFp(f->FFi(z))==f ); + // assert(f->V(f->Prev(z))!=v); + // assert(f->V(f->Next(z))==v || f->V((z+0)%f->VN())==v); + const FaceType *nf=f->FFp(z); + return nf; + } + // Trova il prossimo half-edge di bordo (nhe) // tale che diff --git a/wrap/io_trimesh/export_3ds.h b/wrap/io_trimesh/export_3ds.h index 927cae0f..82424005 100644 --- a/wrap/io_trimesh/export_3ds.h +++ b/wrap/io_trimesh/export_3ds.h @@ -448,7 +448,7 @@ namespace io { /* returns index of the vertex */ - inline static int GetIndexVertex(const SaveMeshType &m, VertexType *p) + inline static int GetIndexVertex(const SaveMeshType &m, const VertexType *p) { return p-&*(m.vert.begin()); } From fa55a9901c3302b97921200cd27f84cfa687924e Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 25 Mar 2021 12:43:08 +0100 Subject: [PATCH 097/140] cmake configuration to build examples --- CMakeLists.txt | 4 ++ apps/CMakeLists.txt | 12 ++-- apps/metro/CMakeLists.txt | 17 ++++- apps/sample/CMakeLists.txt | 64 +++++++++++++++++++ apps/sample/aabb_binary_tree/CMakeLists.txt | 14 ++++ apps/sample/colorspace/CMakeLists.txt | 14 ++++ apps/sample/polygonmesh_base/CMakeLists.txt | 17 +++++ apps/sample/polygonmesh_dual/CMakeLists.txt | 17 +++++ .../polygonmesh_optimize/CMakeLists.txt | 17 +++++ .../CMakeLists.txt | 17 +++++ apps/sample/polygonmesh_smooth/CMakeLists.txt | 17 +++++ apps/sample/sample.pro | 2 +- apps/sample/space_index_2d/CMakeLists.txt | 16 +++++ apps/sample/space_packer/CMakeLists.txt | 30 +++++++++ .../space_rasterized_packer/CMakeLists.txt | 29 +++++++++ apps/sample/trimesh_align_pair/CMakeLists.txt | 17 +++++ apps/sample/trimesh_allocate/CMakeLists.txt | 17 +++++ apps/sample/trimesh_attribute/CMakeLists.txt | 16 +++++ .../trimesh_attribute_saving/CMakeLists.txt | 17 +++++ .../trimesh_ball_pivoting/CMakeLists.txt | 17 +++++ apps/sample/trimesh_base/CMakeLists.txt | 24 ++++--- apps/sample/trimesh_closest/CMakeLists.txt | 17 +++++ apps/sample/trimesh_clustering/CMakeLists.txt | 16 +++++ apps/sample/trimesh_color/CMakeLists.txt | 17 +++++ apps/sample/trimesh_copy/CMakeLists.txt | 17 +++++ apps/sample/trimesh_create/CMakeLists.txt | 16 +++++ apps/sample/trimesh_curvature/CMakeLists.txt | 16 +++++ .../trimesh_cylinder_clipping/CMakeLists.txt | 17 +++++ .../CMakeLists.txt | 17 +++++ apps/sample/trimesh_fitting/CMakeLists.txt | 16 +++++ apps/sample/trimesh_geodesic/CMakeLists.txt | 17 +++++ apps/sample/trimesh_harmonic/CMakeLists.txt | 17 +++++ apps/sample/trimesh_hole/CMakeLists.txt | 17 +++++ .../trimesh_implicit_smooth/CMakeLists.txt | 17 +++++ apps/sample/trimesh_indexing/CMakeLists.txt | 17 +++++ apps/sample/trimesh_inertia/CMakeLists.txt | 16 +++++ .../trimesh_intersection_mesh/CMakeLists.txt | 16 +++++ .../trimesh_intersection_plane/CMakeLists.txt | 16 +++++ apps/sample/trimesh_isosurface/CMakeLists.txt | 17 +++++ apps/sample/trimesh_join/CMakeLists.txt | 17 +++++ apps/sample/trimesh_kdtree/CMakeLists.txt | 17 +++++ .../CMakeLists.txt | 16 +++++ apps/sample/trimesh_normal/CMakeLists.txt | 16 +++++ apps/sample/trimesh_optional/CMakeLists.txt | 17 +++++ .../CMakeLists.txt | 17 +++++ .../trimesh_pointmatching/CMakeLists.txt | 16 +++++ apps/sample/trimesh_ray/CMakeLists.txt | 17 +++++ apps/sample/trimesh_refine/CMakeLists.txt | 17 +++++ apps/sample/trimesh_remeshing/CMakeLists.txt | 17 +++++ apps/sample/trimesh_sampling/CMakeLists.txt | 16 +++++ apps/sample/trimesh_select/CMakeLists.txt | 16 +++++ apps/sample/trimesh_smooth/CMakeLists.txt | 17 +++++ .../trimesh_split_vertex/CMakeLists.txt | 17 +++++ apps/sample/trimesh_texture/CMakeLists.txt | 31 +++++++++ .../trimesh_texture_clean/CMakeLists.txt | 16 +++++ .../trimesh_topological_cut/CMakeLists.txt | 17 +++++ apps/sample/trimesh_topology/CMakeLists.txt | 16 +++++ apps/sample/trimesh_voronoi/CMakeLists.txt | 17 +++++ .../trimesh_voronoiatlas/CMakeLists.txt | 17 +++++ .../trimesh_voronoiclustering/CMakeLists.txt | 17 +++++ .../trimesh_voronoisampling/CMakeLists.txt | 17 +++++ apps/tridecimator/CMakeLists.txt | 17 ++++- 62 files changed, 1074 insertions(+), 18 deletions(-) create mode 100644 apps/sample/CMakeLists.txt create mode 100644 apps/sample/aabb_binary_tree/CMakeLists.txt create mode 100644 apps/sample/colorspace/CMakeLists.txt create mode 100644 apps/sample/polygonmesh_base/CMakeLists.txt create mode 100644 apps/sample/polygonmesh_dual/CMakeLists.txt create mode 100644 apps/sample/polygonmesh_optimize/CMakeLists.txt create mode 100644 apps/sample/polygonmesh_polychord_collapse/CMakeLists.txt create mode 100644 apps/sample/polygonmesh_smooth/CMakeLists.txt create mode 100644 apps/sample/space_index_2d/CMakeLists.txt create mode 100644 apps/sample/space_packer/CMakeLists.txt create mode 100644 apps/sample/space_rasterized_packer/CMakeLists.txt create mode 100644 apps/sample/trimesh_align_pair/CMakeLists.txt create mode 100644 apps/sample/trimesh_allocate/CMakeLists.txt create mode 100644 apps/sample/trimesh_attribute/CMakeLists.txt create mode 100644 apps/sample/trimesh_attribute_saving/CMakeLists.txt create mode 100644 apps/sample/trimesh_ball_pivoting/CMakeLists.txt create mode 100644 apps/sample/trimesh_closest/CMakeLists.txt create mode 100644 apps/sample/trimesh_clustering/CMakeLists.txt create mode 100644 apps/sample/trimesh_color/CMakeLists.txt create mode 100644 apps/sample/trimesh_copy/CMakeLists.txt create mode 100644 apps/sample/trimesh_create/CMakeLists.txt create mode 100644 apps/sample/trimesh_curvature/CMakeLists.txt create mode 100644 apps/sample/trimesh_cylinder_clipping/CMakeLists.txt create mode 100644 apps/sample/trimesh_disk_parametrization/CMakeLists.txt create mode 100644 apps/sample/trimesh_fitting/CMakeLists.txt create mode 100644 apps/sample/trimesh_geodesic/CMakeLists.txt create mode 100644 apps/sample/trimesh_harmonic/CMakeLists.txt create mode 100644 apps/sample/trimesh_hole/CMakeLists.txt create mode 100644 apps/sample/trimesh_implicit_smooth/CMakeLists.txt create mode 100644 apps/sample/trimesh_indexing/CMakeLists.txt create mode 100644 apps/sample/trimesh_inertia/CMakeLists.txt create mode 100644 apps/sample/trimesh_intersection_mesh/CMakeLists.txt create mode 100644 apps/sample/trimesh_intersection_plane/CMakeLists.txt create mode 100644 apps/sample/trimesh_isosurface/CMakeLists.txt create mode 100644 apps/sample/trimesh_join/CMakeLists.txt create mode 100644 apps/sample/trimesh_kdtree/CMakeLists.txt create mode 100644 apps/sample/trimesh_montecarlo_sampling/CMakeLists.txt create mode 100644 apps/sample/trimesh_normal/CMakeLists.txt create mode 100644 apps/sample/trimesh_optional/CMakeLists.txt create mode 100644 apps/sample/trimesh_pointcloud_sampling/CMakeLists.txt create mode 100644 apps/sample/trimesh_pointmatching/CMakeLists.txt create mode 100644 apps/sample/trimesh_ray/CMakeLists.txt create mode 100644 apps/sample/trimesh_refine/CMakeLists.txt create mode 100644 apps/sample/trimesh_remeshing/CMakeLists.txt create mode 100644 apps/sample/trimesh_sampling/CMakeLists.txt create mode 100644 apps/sample/trimesh_select/CMakeLists.txt create mode 100644 apps/sample/trimesh_smooth/CMakeLists.txt create mode 100644 apps/sample/trimesh_split_vertex/CMakeLists.txt create mode 100644 apps/sample/trimesh_texture/CMakeLists.txt create mode 100644 apps/sample/trimesh_texture_clean/CMakeLists.txt create mode 100644 apps/sample/trimesh_topological_cut/CMakeLists.txt create mode 100644 apps/sample/trimesh_topology/CMakeLists.txt create mode 100644 apps/sample/trimesh_voronoi/CMakeLists.txt create mode 100644 apps/sample/trimesh_voronoiatlas/CMakeLists.txt create mode 100644 apps/sample/trimesh_voronoiclustering/CMakeLists.txt create mode 100644 apps/sample/trimesh_voronoisampling/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index d4790194..fc28d096 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,9 @@ option(ALLOW_SYSTEM_EIGEN "Allow use of system-provided Eigen" ON) option(VCG_HEADER_ONLY "Use VCG library in header only mode" ON) option(VCG_BUILD_EXAMPLES "Build a set of examples of the library" OFF) +set (VCG_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}) +set (VCG_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE) + # Prefer GLVND if(POLICY CMP0072) cmake_policy(SET CMP0072 NEW) @@ -296,4 +299,5 @@ endif() if(VCG_BUILD_EXAMPLES) #TODO make the list of samples to build + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/apps) endif() diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index dc516ffe..7af54e3a 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,9 +1,7 @@ -cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_BUILD_TYPE Release) -set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required... -set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11 -include_directories(../) -include_directories(../eigenlib) +cmake_minimum_required(VERSION 3.13) + +project(VCGApps) + +add_subdirectory(sample) add_subdirectory(metro) add_subdirectory(tridecimator) diff --git a/apps/metro/CMakeLists.txt b/apps/metro/CMakeLists.txt index f628ace7..aa5ec471 100644 --- a/apps/metro/CMakeLists.txt +++ b/apps/metro/CMakeLists.txt @@ -1,2 +1,17 @@ +cmake_minimum_required(VERSION 3.13) project (metro) -add_executable(metro metro.cpp ../../wrap/ply/plylib.cpp) + +if (VCG_HEADER_ONLY) + set(SOURCES + metro.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(metro + ${SOURCES}) + +target_link_libraries( + metro + PUBLIC + vcglib + ) diff --git a/apps/sample/CMakeLists.txt b/apps/sample/CMakeLists.txt new file mode 100644 index 00000000..a1846e1b --- /dev/null +++ b/apps/sample/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.13) +project(VCGExamples) + +set(VCG_EXAMPLE_PROJECTS + aabb_binary_tree + colorspace + polygonmesh_base + polygonmesh_dual + polygonmesh_optimize + polygonmesh_polychord_collapse + polygonmesh_smooth + space_index_2d + space_packer + space_rasterized_packer + trimesh_align_pair + trimesh_allocate + trimesh_attribute + trimesh_attribute_saving + trimesh_ball_pivoting + trimesh_base + trimesh_closest + trimesh_clustering + trimesh_color + trimesh_copy + trimesh_create + trimesh_curvature + trimesh_cylinder_clipping + trimesh_disk_parametrization + trimesh_fitting + trimesh_geodesic + trimesh_harmonic + trimesh_hole + trimesh_implicit_smooth + trimesh_indexing + trimesh_inertia + trimesh_intersection_plane + trimesh_intersection_mesh + trimesh_isosurface + trimesh_join + trimesh_kdtree + trimesh_montecarlo_sampling + trimesh_normal + trimesh_optional + trimesh_pointmatching + trimesh_pointcloud_sampling + trimesh_ray + trimesh_refine + trimesh_remeshing + trimesh_sampling + trimesh_select + trimesh_smooth + trimesh_split_vertex + trimesh_texture + trimesh_texture_clean + trimesh_topology + trimesh_topological_cut + trimesh_voronoi + trimesh_voronoiatlas + trimesh_voronoiclustering + trimesh_voronoisampling) + +foreach(VCG_EXAMPLE ${VCG_EXAMPLE_PROJECTS}) + add_subdirectory(${VCG_EXAMPLE}) +endforeach() diff --git a/apps/sample/aabb_binary_tree/CMakeLists.txt b/apps/sample/aabb_binary_tree/CMakeLists.txt new file mode 100644 index 00000000..bccc0ec7 --- /dev/null +++ b/apps/sample/aabb_binary_tree/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.13) +project(aabb_binary_tree) + +set(SOURCES + aabb_binary_tree.cpp) + +add_executable(aabb_binary_tree + ${SOURCES}) + +target_link_libraries( + aabb_binary_tree + PUBLIC + vcglib + ) diff --git a/apps/sample/colorspace/CMakeLists.txt b/apps/sample/colorspace/CMakeLists.txt new file mode 100644 index 00000000..c6b2d5a0 --- /dev/null +++ b/apps/sample/colorspace/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.13) +project(colorspace) + +set(SOURCES + colorspace.cpp) + +add_executable(colorspace + ${SOURCES}) + +target_link_libraries( + colorspace + PUBLIC + vcglib + ) diff --git a/apps/sample/polygonmesh_base/CMakeLists.txt b/apps/sample/polygonmesh_base/CMakeLists.txt new file mode 100644 index 00000000..567a8a85 --- /dev/null +++ b/apps/sample/polygonmesh_base/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(polygonmesh_base) + +if (VCG_HEADER_ONLY) + set(SOURCES + polygonmesh.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(polygonmesh_base + ${SOURCES}) + +target_link_libraries( + polygonmesh_base + PUBLIC + vcglib + ) diff --git a/apps/sample/polygonmesh_dual/CMakeLists.txt b/apps/sample/polygonmesh_dual/CMakeLists.txt new file mode 100644 index 00000000..40018f75 --- /dev/null +++ b/apps/sample/polygonmesh_dual/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(polygonmesh_dual) + +if (VCG_HEADER_ONLY) + set(SOURCES + polygonmesh_dual.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(polygonmesh_dual + ${SOURCES}) + +target_link_libraries( + polygonmesh_dual + PUBLIC + vcglib + ) diff --git a/apps/sample/polygonmesh_optimize/CMakeLists.txt b/apps/sample/polygonmesh_optimize/CMakeLists.txt new file mode 100644 index 00000000..07f572db --- /dev/null +++ b/apps/sample/polygonmesh_optimize/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(polygonmesh_optimize) + +if (VCG_HEADER_ONLY) + set(SOURCES + polygonmesh_optimize.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(polygonmesh_optimize + ${SOURCES}) + +target_link_libraries( + polygonmesh_optimize + PUBLIC + vcglib + ) diff --git a/apps/sample/polygonmesh_polychord_collapse/CMakeLists.txt b/apps/sample/polygonmesh_polychord_collapse/CMakeLists.txt new file mode 100644 index 00000000..0ac97fc7 --- /dev/null +++ b/apps/sample/polygonmesh_polychord_collapse/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(polygonmesh_polychord_collapse) + +if (VCG_HEADER_ONLY) + set(SOURCES + polygonmesh_polychord_collapse.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(polygonmesh_polychord_collapse + ${SOURCES}) + +target_link_libraries( + polygonmesh_polychord_collapse + PUBLIC + vcglib + ) diff --git a/apps/sample/polygonmesh_smooth/CMakeLists.txt b/apps/sample/polygonmesh_smooth/CMakeLists.txt new file mode 100644 index 00000000..002bb6db --- /dev/null +++ b/apps/sample/polygonmesh_smooth/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(polygonmesh_smooth) + +if (VCG_HEADER_ONLY) + set(SOURCES + polygonmesh_smooth.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(polygonmesh_smooth + ${SOURCES}) + +target_link_libraries( + polygonmesh_smooth + PUBLIC + vcglib + ) diff --git a/apps/sample/sample.pro b/apps/sample/sample.pro index 1036b4d2..0a99190e 100644 --- a/apps/sample/sample.pro +++ b/apps/sample/sample.pro @@ -60,4 +60,4 @@ SUBDIRS = \ trimesh_voronoi \ trimesh_voronoiatlas \ trimesh_voronoiclustering \ - trimesh_voronoisampling \ + trimesh_voronoisampling diff --git a/apps/sample/space_index_2d/CMakeLists.txt b/apps/sample/space_index_2d/CMakeLists.txt new file mode 100644 index 00000000..b5c07abd --- /dev/null +++ b/apps/sample/space_index_2d/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(space_index_2d) + +if (VCG_HEADER_ONLY) + set(SOURCES + space_index_2d.cpp) +endif() + +add_executable(space_index_2d + ${SOURCES}) + +target_link_libraries( + space_index_2d + PUBLIC + vcglib + ) diff --git a/apps/sample/space_packer/CMakeLists.txt b/apps/sample/space_packer/CMakeLists.txt new file mode 100644 index 00000000..69d3e0fd --- /dev/null +++ b/apps/sample/space_packer/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.13) +project(space_packer) + +find_package( + Qt5 + COMPONENTS OpenGL Svg) + +if (TARGET Qt5::OpenGL AND TARGET Qt5::Svg) + + if (VCG_HEADER_ONLY) + set(SOURCES + space_packer.cpp + ${VCG_INCLUDE_DIRS}/wrap/qt/Outline2ToQImage.cpp + ${VCG_INCLUDE_DIRS}/wrap/qt/outline2_rasterizer.cpp) + endif() + + add_executable(space_packer + ${SOURCES}) + + target_link_libraries( + space_packer + PUBLIC + vcglib + Qt5::OpenGL + Qt5::Svg + ) +else() + message( + STATUS "VCG examples - Skipping space_packer example") +endif() diff --git a/apps/sample/space_rasterized_packer/CMakeLists.txt b/apps/sample/space_rasterized_packer/CMakeLists.txt new file mode 100644 index 00000000..bbe86336 --- /dev/null +++ b/apps/sample/space_rasterized_packer/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.13) +project(space_rasterized_packer) + +find_package( + Qt5 + COMPONENTS OpenGL Svg) + +if (TARGET Qt5::OpenGL AND TARGET Qt5::Svg) + if (VCG_HEADER_ONLY) + set(SOURCES + space_rasterized_packer.cpp + ${VCG_INCLUDE_DIRS}/wrap/qt/Outline2ToQImage.cpp + ${VCG_INCLUDE_DIRS}/wrap/qt/outline2_rasterizer.cpp) + endif() + + add_executable(space_rasterized_packer + ${SOURCES}) + + target_link_libraries( + space_rasterized_packer + PUBLIC + vcglib + Qt5::OpenGL + Qt5::Svg + ) +else() + message( + STATUS "VCG examples - Skipping space_rasterized_packer example") +endif() diff --git a/apps/sample/trimesh_align_pair/CMakeLists.txt b/apps/sample/trimesh_align_pair/CMakeLists.txt new file mode 100644 index 00000000..34ebd62c --- /dev/null +++ b/apps/sample/trimesh_align_pair/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_align_pair) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_align_pair.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_align_pair + ${SOURCES}) + +target_link_libraries( + trimesh_align_pair + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_allocate/CMakeLists.txt b/apps/sample/trimesh_allocate/CMakeLists.txt new file mode 100644 index 00000000..00e5dafd --- /dev/null +++ b/apps/sample/trimesh_allocate/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_allocate) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_allocate.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_allocate + ${SOURCES}) + +target_link_libraries( + trimesh_allocate + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_attribute/CMakeLists.txt b/apps/sample/trimesh_attribute/CMakeLists.txt new file mode 100644 index 00000000..54a08850 --- /dev/null +++ b/apps/sample/trimesh_attribute/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_attribute) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_attribute.cpp) +endif() + +add_executable(trimesh_attribute + ${SOURCES}) + +target_link_libraries( + trimesh_attribute + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_attribute_saving/CMakeLists.txt b/apps/sample/trimesh_attribute_saving/CMakeLists.txt new file mode 100644 index 00000000..56572ba8 --- /dev/null +++ b/apps/sample/trimesh_attribute_saving/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_attribute_saving) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_attribute_saving.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_attribute_saving + ${SOURCES}) + +target_link_libraries( + trimesh_attribute_saving + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_ball_pivoting/CMakeLists.txt b/apps/sample/trimesh_ball_pivoting/CMakeLists.txt new file mode 100644 index 00000000..df6f55eb --- /dev/null +++ b/apps/sample/trimesh_ball_pivoting/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_ball_pivoting) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_ball_pivoting.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_ball_pivoting + ${SOURCES}) + +target_link_libraries( + trimesh_ball_pivoting + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_base/CMakeLists.txt b/apps/sample/trimesh_base/CMakeLists.txt index 8939a675..b87de841 100644 --- a/apps/sample/trimesh_base/CMakeLists.txt +++ b/apps/sample/trimesh_base/CMakeLists.txt @@ -1,8 +1,16 @@ -cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required... -set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11 -project (trimesh_base) -add_executable(trimesh_base trimesh_base.cpp) -include_directories(../../..) -include_directories(../../../eigenlib) +cmake_minimum_required(VERSION 3.13) +project(trimesh_base) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_base.cpp) +endif() + +add_executable(trimesh_base + ${SOURCES}) + +target_link_libraries( + trimesh_base + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_closest/CMakeLists.txt b/apps/sample/trimesh_closest/CMakeLists.txt new file mode 100644 index 00000000..4e61aa77 --- /dev/null +++ b/apps/sample/trimesh_closest/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_closest) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_closest.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_closest + ${SOURCES}) + +target_link_libraries( + trimesh_closest + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_clustering/CMakeLists.txt b/apps/sample/trimesh_clustering/CMakeLists.txt new file mode 100644 index 00000000..ec0a1361 --- /dev/null +++ b/apps/sample/trimesh_clustering/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_clustering) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_clustering.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_clustering + ${SOURCES}) + +target_link_libraries( + trimesh_clustering + PUBLIC vcglib + ) diff --git a/apps/sample/trimesh_color/CMakeLists.txt b/apps/sample/trimesh_color/CMakeLists.txt new file mode 100644 index 00000000..ecf09f09 --- /dev/null +++ b/apps/sample/trimesh_color/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_color) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_color.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_color + ${SOURCES}) + +target_link_libraries( + trimesh_color + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_copy/CMakeLists.txt b/apps/sample/trimesh_copy/CMakeLists.txt new file mode 100644 index 00000000..431fb603 --- /dev/null +++ b/apps/sample/trimesh_copy/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_copy) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_copy.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_copy + ${SOURCES}) + +target_link_libraries( + trimesh_copy + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_create/CMakeLists.txt b/apps/sample/trimesh_create/CMakeLists.txt new file mode 100644 index 00000000..a9ba842b --- /dev/null +++ b/apps/sample/trimesh_create/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_create) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_create.cpp) +endif() + +add_executable(trimesh_create + ${SOURCES}) + +target_link_libraries( + trimesh_create + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_curvature/CMakeLists.txt b/apps/sample/trimesh_curvature/CMakeLists.txt new file mode 100644 index 00000000..a09fe6e1 --- /dev/null +++ b/apps/sample/trimesh_curvature/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_curvature) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_curvature.cpp) +endif() + +add_executable(trimesh_curvature + ${SOURCES}) + +target_link_libraries( + trimesh_curvature + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_cylinder_clipping/CMakeLists.txt b/apps/sample/trimesh_cylinder_clipping/CMakeLists.txt new file mode 100644 index 00000000..96ceb24c --- /dev/null +++ b/apps/sample/trimesh_cylinder_clipping/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_cylinder_clipping) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_cylinder_clipping.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_cylinder_clipping + ${SOURCES}) + +target_link_libraries( + trimesh_cylinder_clipping + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_disk_parametrization/CMakeLists.txt b/apps/sample/trimesh_disk_parametrization/CMakeLists.txt new file mode 100644 index 00000000..02edee20 --- /dev/null +++ b/apps/sample/trimesh_disk_parametrization/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_disk_parametrization) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_disk_parametrization.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_disk_parametrization + ${SOURCES}) + +target_link_libraries( + trimesh_disk_parametrization + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_fitting/CMakeLists.txt b/apps/sample/trimesh_fitting/CMakeLists.txt new file mode 100644 index 00000000..c93263b9 --- /dev/null +++ b/apps/sample/trimesh_fitting/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_fitting) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_fitting.cpp) +endif() + +add_executable(trimesh_fitting + ${SOURCES}) + +target_link_libraries( + trimesh_fitting + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_geodesic/CMakeLists.txt b/apps/sample/trimesh_geodesic/CMakeLists.txt new file mode 100644 index 00000000..f410e7c2 --- /dev/null +++ b/apps/sample/trimesh_geodesic/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_geodesic) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_geodesic.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_geodesic + ${SOURCES}) + +target_link_libraries( + trimesh_geodesic + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_harmonic/CMakeLists.txt b/apps/sample/trimesh_harmonic/CMakeLists.txt new file mode 100644 index 00000000..b525fced --- /dev/null +++ b/apps/sample/trimesh_harmonic/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_harmonic) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_harmonic.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_harmonic + ${SOURCES}) + +target_link_libraries( + trimesh_harmonic + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_hole/CMakeLists.txt b/apps/sample/trimesh_hole/CMakeLists.txt new file mode 100644 index 00000000..da677588 --- /dev/null +++ b/apps/sample/trimesh_hole/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_hole) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_hole.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_hole + ${SOURCES}) + +target_link_libraries( + trimesh_hole + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_implicit_smooth/CMakeLists.txt b/apps/sample/trimesh_implicit_smooth/CMakeLists.txt new file mode 100644 index 00000000..a9c3f74d --- /dev/null +++ b/apps/sample/trimesh_implicit_smooth/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_implicit_smooth) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_implicit_smooth.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_implicit_smooth + ${SOURCES}) + +target_link_libraries( + trimesh_implicit_smooth + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_indexing/CMakeLists.txt b/apps/sample/trimesh_indexing/CMakeLists.txt new file mode 100644 index 00000000..80df98e5 --- /dev/null +++ b/apps/sample/trimesh_indexing/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_indexing) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_indexing.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_indexing + ${SOURCES}) + +target_link_libraries( + trimesh_indexing + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_inertia/CMakeLists.txt b/apps/sample/trimesh_inertia/CMakeLists.txt new file mode 100644 index 00000000..49dc45ed --- /dev/null +++ b/apps/sample/trimesh_inertia/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_inertia) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_inertia.cpp) +endif() + +add_executable(trimesh_inertia + ${SOURCES}) + +target_link_libraries( + trimesh_inertia + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_intersection_mesh/CMakeLists.txt b/apps/sample/trimesh_intersection_mesh/CMakeLists.txt new file mode 100644 index 00000000..d76bb7ad --- /dev/null +++ b/apps/sample/trimesh_intersection_mesh/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_intersection_mesh) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_intersection_mesh.cpp) +endif() + +add_executable(trimesh_intersection_mesh + ${SOURCES}) + +target_link_libraries( + trimesh_intersection_mesh + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_intersection_plane/CMakeLists.txt b/apps/sample/trimesh_intersection_plane/CMakeLists.txt new file mode 100644 index 00000000..0a317f06 --- /dev/null +++ b/apps/sample/trimesh_intersection_plane/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_intersection_plane) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_intersection_plane.cpp) +endif() + +add_executable(trimesh_intersection_plane + ${SOURCES}) + +target_link_libraries( + trimesh_intersection_plane + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_isosurface/CMakeLists.txt b/apps/sample/trimesh_isosurface/CMakeLists.txt new file mode 100644 index 00000000..d1d07423 --- /dev/null +++ b/apps/sample/trimesh_isosurface/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_isosurface) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_isosurface.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_isosurface + ${SOURCES}) + +target_link_libraries( + trimesh_isosurface + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_join/CMakeLists.txt b/apps/sample/trimesh_join/CMakeLists.txt new file mode 100644 index 00000000..e783f456 --- /dev/null +++ b/apps/sample/trimesh_join/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_join) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_join.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_join + ${SOURCES}) + +target_link_libraries( + trimesh_join + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_kdtree/CMakeLists.txt b/apps/sample/trimesh_kdtree/CMakeLists.txt new file mode 100644 index 00000000..79587c32 --- /dev/null +++ b/apps/sample/trimesh_kdtree/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_kdtree) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_kdtree.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_kdtree + ${SOURCES}) + +target_link_libraries( + trimesh_kdtree + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_montecarlo_sampling/CMakeLists.txt b/apps/sample/trimesh_montecarlo_sampling/CMakeLists.txt new file mode 100644 index 00000000..6ae8946e --- /dev/null +++ b/apps/sample/trimesh_montecarlo_sampling/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_montecarlo_sampling) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_montecarlo_sampling.cpp) +endif() + +add_executable(trimesh_montecarlo_sampling + ${SOURCES}) + +target_link_libraries( + trimesh_montecarlo_sampling + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_normal/CMakeLists.txt b/apps/sample/trimesh_normal/CMakeLists.txt new file mode 100644 index 00000000..06f24aca --- /dev/null +++ b/apps/sample/trimesh_normal/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_normal) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_normal.cpp) +endif() + +add_executable(trimesh_normal + ${SOURCES}) + +target_link_libraries( + trimesh_normal + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_optional/CMakeLists.txt b/apps/sample/trimesh_optional/CMakeLists.txt new file mode 100644 index 00000000..f6195fc2 --- /dev/null +++ b/apps/sample/trimesh_optional/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_optional) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_optional.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_optional + ${SOURCES}) + +target_link_libraries( + trimesh_optional + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_pointcloud_sampling/CMakeLists.txt b/apps/sample/trimesh_pointcloud_sampling/CMakeLists.txt new file mode 100644 index 00000000..1e8cfa07 --- /dev/null +++ b/apps/sample/trimesh_pointcloud_sampling/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_pointcloud_sampling) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_pointcloud_sampling.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_pointcloud_sampling + ${SOURCES}) + +target_link_libraries( + trimesh_pointcloud_sampling + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_pointmatching/CMakeLists.txt b/apps/sample/trimesh_pointmatching/CMakeLists.txt new file mode 100644 index 00000000..f7ba0aae --- /dev/null +++ b/apps/sample/trimesh_pointmatching/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_pointmatching) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_pointmatching.cpp) +endif() + +add_executable(trimesh_pointmatching + ${SOURCES}) + +target_link_libraries( + trimesh_pointmatching + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_ray/CMakeLists.txt b/apps/sample/trimesh_ray/CMakeLists.txt new file mode 100644 index 00000000..e9b07b96 --- /dev/null +++ b/apps/sample/trimesh_ray/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_ray) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_ray.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_ray + ${SOURCES}) + +target_link_libraries( + trimesh_ray + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_refine/CMakeLists.txt b/apps/sample/trimesh_refine/CMakeLists.txt new file mode 100644 index 00000000..88bbe644 --- /dev/null +++ b/apps/sample/trimesh_refine/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_refine) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_refine.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_refine + ${SOURCES}) + +target_link_libraries( + trimesh_refine + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_remeshing/CMakeLists.txt b/apps/sample/trimesh_remeshing/CMakeLists.txt new file mode 100644 index 00000000..72377e8a --- /dev/null +++ b/apps/sample/trimesh_remeshing/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_remeshing) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_remeshing.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_remeshing + ${SOURCES}) + +target_link_libraries( + trimesh_remeshing + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_sampling/CMakeLists.txt b/apps/sample/trimesh_sampling/CMakeLists.txt new file mode 100644 index 00000000..a720ceeb --- /dev/null +++ b/apps/sample/trimesh_sampling/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_sampling) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_sampling.cpp) +endif() + +add_executable(trimesh_sampling + ${SOURCES}) + +target_link_libraries( + trimesh_sampling + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_select/CMakeLists.txt b/apps/sample/trimesh_select/CMakeLists.txt new file mode 100644 index 00000000..3fa8e8c3 --- /dev/null +++ b/apps/sample/trimesh_select/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_select) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_select.cpp) +endif() + +add_executable(trimesh_select + ${SOURCES}) + +target_link_libraries( + trimesh_select + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_smooth/CMakeLists.txt b/apps/sample/trimesh_smooth/CMakeLists.txt new file mode 100644 index 00000000..a3bbddcd --- /dev/null +++ b/apps/sample/trimesh_smooth/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_smooth) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_smooth.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_smooth + ${SOURCES}) + +target_link_libraries( + trimesh_smooth + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_split_vertex/CMakeLists.txt b/apps/sample/trimesh_split_vertex/CMakeLists.txt new file mode 100644 index 00000000..09a75511 --- /dev/null +++ b/apps/sample/trimesh_split_vertex/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_split_vertex) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_split_vertex.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_split_vertex + ${SOURCES}) + +target_link_libraries( + trimesh_split_vertex + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_texture/CMakeLists.txt b/apps/sample/trimesh_texture/CMakeLists.txt new file mode 100644 index 00000000..b4328dd7 --- /dev/null +++ b/apps/sample/trimesh_texture/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_texture) + +find_package( + Qt5 + COMPONENTS OpenGL Svg) + +if (TARGET Qt5::OpenGL AND TARGET Qt5::Svg) + + if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_texture.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp + ${VCG_INCLUDE_DIRS}/wrap/qt/Outline2ToQImage.cpp + ${VCG_INCLUDE_DIRS}/wrap/qt/outline2_rasterizer.cpp) + endif() + + add_executable(trimesh_texture + ${SOURCES}) + + target_link_libraries( + trimesh_texture + PUBLIC + vcglib + Qt5::OpenGL + Qt5::Svg + ) +else() + message( + STATUS "VCG examples - Skipping trimesh_texture example") +endif() diff --git a/apps/sample/trimesh_texture_clean/CMakeLists.txt b/apps/sample/trimesh_texture_clean/CMakeLists.txt new file mode 100644 index 00000000..5d325ee8 --- /dev/null +++ b/apps/sample/trimesh_texture_clean/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_texture_clean) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_texture_clean.cpp) +endif() + +add_executable(trimesh_texture_clean + ${SOURCES}) + +target_link_libraries( + trimesh_texture_clean + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_topological_cut/CMakeLists.txt b/apps/sample/trimesh_topological_cut/CMakeLists.txt new file mode 100644 index 00000000..871b1236 --- /dev/null +++ b/apps/sample/trimesh_topological_cut/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_topological_cut) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_topological_cut.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_topological_cut + ${SOURCES}) + +target_link_libraries( + trimesh_topological_cut + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_topology/CMakeLists.txt b/apps/sample/trimesh_topology/CMakeLists.txt new file mode 100644 index 00000000..bb0b5471 --- /dev/null +++ b/apps/sample/trimesh_topology/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_topology) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_topology.cpp) +endif() + +add_executable(trimesh_topology + ${SOURCES}) + +target_link_libraries( + trimesh_topology + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_voronoi/CMakeLists.txt b/apps/sample/trimesh_voronoi/CMakeLists.txt new file mode 100644 index 00000000..9ce633cb --- /dev/null +++ b/apps/sample/trimesh_voronoi/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_voronoi) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_voronoi.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_voronoi + ${SOURCES}) + +target_link_libraries( + trimesh_voronoi + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_voronoiatlas/CMakeLists.txt b/apps/sample/trimesh_voronoiatlas/CMakeLists.txt new file mode 100644 index 00000000..3f639e58 --- /dev/null +++ b/apps/sample/trimesh_voronoiatlas/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_voronoiatlas) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_voronoiatlas.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_voronoiatlas + ${SOURCES}) + +target_link_libraries( + trimesh_voronoiatlas + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_voronoiclustering/CMakeLists.txt b/apps/sample/trimesh_voronoiclustering/CMakeLists.txt new file mode 100644 index 00000000..2e0bfc26 --- /dev/null +++ b/apps/sample/trimesh_voronoiclustering/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_voronoiclustering) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_voronoiclustering.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_voronoiclustering + ${SOURCES}) + +target_link_libraries( + trimesh_voronoiclustering + PUBLIC + vcglib + ) diff --git a/apps/sample/trimesh_voronoisampling/CMakeLists.txt b/apps/sample/trimesh_voronoisampling/CMakeLists.txt new file mode 100644 index 00000000..df908eb5 --- /dev/null +++ b/apps/sample/trimesh_voronoisampling/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(trimesh_voronoisampling) + +if (VCG_HEADER_ONLY) + set(SOURCES + trimesh_voronoisampling.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(trimesh_voronoisampling + ${SOURCES}) + +target_link_libraries( + trimesh_voronoisampling + PUBLIC + vcglib + ) diff --git a/apps/tridecimator/CMakeLists.txt b/apps/tridecimator/CMakeLists.txt index 7f337fcb..0cf6e0fe 100644 --- a/apps/tridecimator/CMakeLists.txt +++ b/apps/tridecimator/CMakeLists.txt @@ -1,2 +1,17 @@ +cmake_minimum_required(VERSION 3.13) project (tridecimator) -add_executable(tridecimator tridecimator.cpp ../../wrap/ply/plylib.cpp) + +if (VCG_HEADER_ONLY) + set(SOURCES + tridecimator.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) +endif() + +add_executable(tridecimator + ${SOURCES}) + +target_link_libraries( + tridecimator + PUBLIC + vcglib + ) From ad75e3559363627e655a2f013e0dd99e1e6de300 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 25 Mar 2021 15:19:14 +0100 Subject: [PATCH 098/140] codespell - see #92 --- apps/QT/trimesh_QT/glarea.h | 8 +- apps/QT/trimesh_QT_shared/glarea.h | 8 +- apps/QT/trimesh_ant_freeglut/main.cpp | 32 ++-- apps/plymc/simplemeshprovider.h | 2 +- vcg/complex/algorithms/clean.h | 2 +- vcg/complex/algorithms/point_sampling.h | 2 +- vcg/complex/algorithms/refine.h | 2 +- .../algorithms/textcoord_optimization.h | 162 +++++++++--------- vcg/math/matrix44.h | 2 +- vcg/math/shot.h | 4 +- vcg/space/box.h | 20 +-- vcg/space/box2.h | 8 +- vcg/space/line2.h | 2 +- vcg/space/line3.h | 2 +- vcg/space/rasterized_outline2_packer.h | 4 +- vcg/space/ray2.h | 2 +- vcg/space/ray3.h | 2 +- wrap/gui/activecoordinateframe.cpp | 32 ++-- wrap/gui/activecoordinateframe.h | 18 +- wrap/gui/coordinateframe.h | 4 +- wrap/gui/trackball.h | 26 +-- wrap/io_tetramesh/io_ply.h | 14 +- wrap/io_trimesh/import_ptx.h | 8 +- wrap/io_trimesh/io_ply.h | 62 +++---- wrap/math/sparse_matrix.h | 14 +- 25 files changed, 221 insertions(+), 221 deletions(-) diff --git a/apps/QT/trimesh_QT/glarea.h b/apps/QT/trimesh_QT/glarea.h index 75b17dfa..aaf5c1c1 100644 --- a/apps/QT/trimesh_QT/glarea.h +++ b/apps/QT/trimesh_QT/glarea.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * - * This program is free software; you can redistribute it and/or modify * + * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -64,10 +64,10 @@ class CMesh : public vcg::tri::TriMesh< std::vector, std::vectorbbox.Center()); + glTranslate(-glWrap.m->bbox.Center()); // the trimesh drawing calls switch(drawmode) { - case SMOOTH: + case SMOOTH: glWrap.Draw (); break; - case PERPOINTS: + case PERPOINTS: glWrap.Draw (); break; - case WIRE: + case WIRE: glWrap.Draw (); break; - case FLATWIRE: + case FLATWIRE: glWrap.Draw (); break; - case HIDDEN: + case HIDDEN: glWrap.Draw (); break; - case FLAT: + case FLAT: glWrap.Draw (); break; - default: + default: break; } @@ -185,7 +185,7 @@ void initMesh() } void TW_CALL loadMesh(void *) -{ +{ if(filename==0) return; int err=vcg::tri::io::ImporterPLY::Open(mesh,(char*)filename); if(err!=0){ @@ -276,7 +276,7 @@ int main(int argc, char *argv[]) // (note that AntTweakBar could also be intialized after GLUT, no matter) if( !TwInit(TW_OPENGL, NULL) ) { - // A fatal error occured + // A fatal error occured fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError()); return 1; } @@ -311,12 +311,12 @@ int main(int argc, char *argv[]) glutKeyboardFunc(keyPressEvent); glutKeyboardUpFunc(keyReleaseEvent); - + glutMouseWheelFunc(wheelEvent); bar = TwNewBar("TweakBar"); TwCopyCDStringToClientFunc (CopyCDStringToClient); - + TwAddVarRW(bar,"Input",TW_TYPE_CDSTRING,&filename," label='Filepath' group=SetMesh help=` Name of the file to load` "); TwAddButton(bar,"Load from file",loadMesh,0, " label='Load Mesh' group=SetMesh help=`load the mesh` "); TwAddButton(bar,"Use tetrahedron",loadTetrahedron,0, " label='Make Tetrahedron' group=SetMesh help=`use tetrahedron.` "); diff --git a/apps/plymc/simplemeshprovider.h b/apps/plymc/simplemeshprovider.h index 9505d33b..e6c38402 100644 --- a/apps/plymc/simplemeshprovider.h +++ b/apps/plymc/simplemeshprovider.h @@ -112,7 +112,7 @@ template // ALNParser::ParseALN(rmaps, alnName); // for(size_t i=0; i minVertVec; std::vector< VertexPointer > maxVertVec; - // The set of directions to be choosen + // The set of directions to be chosen std::vector< CoordType > dirVec; dirVec.push_back(CoordType(1,0,0)); dirVec.push_back(CoordType(0,1,0)); diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index 702dbdef..d5e711f8 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -1005,7 +1005,7 @@ static void AllEdge(MeshType & m, VertexSampler &ps) // Regular Uniform Edge sampling // Each edge is subdivided in a number of pieces proprtional to its length -// Sample are choosen without touching the vertices. +// Samples are chosen without touching the vertices. static void EdgeUniform(MeshType & m, VertexSampler &ps,int sampleNum, bool sampleFauxEdge=true) { diff --git a/vcg/complex/algorithms/refine.h b/vcg/complex/algorithms/refine.h index cd3c75a6..082a0228 100644 --- a/vcg/complex/algorithms/refine.h +++ b/vcg/complex/algorithms/refine.h @@ -303,7 +303,7 @@ Given a mesh the following function refines it according to two functor objects: - a predicate that tells if a given edge must be splitted -- a functor that gives you the new poistion of the created vertices (starting from an edge) +- a functor that gives you the new position of the created vertices (starting from an edge) If RefineSelected is true only selected faces are taken into account for being splitted. diff --git a/vcg/complex/algorithms/textcoord_optimization.h b/vcg/complex/algorithms/textcoord_optimization.h index 831e92cd..3c822ace 100644 --- a/vcg/complex/algorithms/textcoord_optimization.h +++ b/vcg/complex/algorithms/textcoord_optimization.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -45,13 +45,13 @@ namespace tri /* Base class for all Texture Optimizers*/ -template +template class TextureOptimizer{ protected: MESH_TYPE &m; SimpleTempData isFixed; public: - + /* Tpyes */ typedef MESH_TYPE MeshType; typedef typename MESH_TYPE::VertexIterator VertexIterator; @@ -59,26 +59,26 @@ public: typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::ScalarType ScalarType; - - + + /* Access functions */ const MeshType & Mesh() const {return m;} MeshType & Mesh() {return m;} - + /* Constructior */ TextureOptimizer(MeshType &_m):m(_m),isFixed(_m.vert){ assert(m.HasPerVertexTexture()); } - - // initializes on current geometry + + // initializes on current geometry virtual void TargetCurrentGeometry()=0; - - // performs an interation. Returns largest movement. + + // performs an iteration. Returns largest movement. virtual ScalarType Iterate()=0; - + // performs an iteration (faster, but it does not tell how close it is to stopping) virtual void IterateBlind()=0; - + // performs iteration virtual ScalarType IterateN(int step){ for (int i=0; i1) return this->Iterate(); else return 0; } - + // performs iterations until convergence. bool IterateUntilConvergence(ScalarType threshold=0.0001, int maxite=5000){ int i; @@ -95,34 +95,34 @@ public: } return true; } - + // desctuctor: free temporary field ~TextureOptimizer(){ isFixed.Stop(); }; - + // set the current border as fixed (forced to stay in position during text optimization) void SetBorderAsFixed(){ isFixed.Start(); for (VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) { - isFixed[v]=(v->IsB())?1:0; - } + isFixed[v]=(v->IsB())?1:0; + } } - + // everything moves, no vertex must fixed during texture optimization) void SetNothingAsFixed(){ isFixed.Start(); for (VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) { - isFixed[v]=0; - } + isFixed[v]=0; + } } - + // fix a given vertex void FixVertex(const VertexType *v, bool fix=true){ isFixed[v]=(fix)?1:0; } - - + + }; @@ -130,12 +130,12 @@ public: /* AREA PRESERVING TEXTURE OPTIMIZATION -as in: Degener, P., Meseth, J., Klein, R. +as in: Degener, P., Meseth, J., Klein, R. "An adaptable surface parameterization method." - Proc. of the 12th International Meshing oundtable, 201–213 [2003]. + Proc. of the 12th International Meshing oundtable, 201-213 [2003]. Features: - + :) - Balances angle and area distortions (best results!). :) - Can choose how to balance area and angle preservation (see SetTheta) theta=0 -> pure conformal (use MIPS instead!) @@ -144,12 +144,12 @@ Features: :( - Slowest method. :( - Requires a fixed boundary, else expands forever in texture space (unless theta=0). :( - Diverges in presence of flipped faces (unless theta=0). -:( - Requires a speed parameter to be set. +:( - Requires a speed parameter to be set. Speed too large => when close, bounces back and forth around minimum, w/o getting any closer. Lower speed => longer convercence times */ -template +template class AreaPreservingTextureOptimizer:public TextureOptimizer{ public: /* Types */ @@ -159,34 +159,34 @@ public: typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::ScalarType ScalarType; - + private: typedef TextureOptimizer Super; // superclass (commodity) - + // extra data per face: [0..3] -> cotangents. [4] -> area*2 SimpleTempData > data; SimpleTempData > sum; - + ScalarType totArea; ScalarType speed; - + int theta; - + public: - + // constructor and destructor AreaPreservingTextureOptimizer(MeshType &_m):Super(_m),data(_m.face),sum(_m.vert){ speed=0.001; theta=3; } - + ~AreaPreservingTextureOptimizer(){ data.Stop(); sum.Stop(); Super::isFixed.Stop(); } - + void SetSpeed(ScalarType _speed){ speed=_speed; } @@ -194,7 +194,7 @@ public: ScalarType GetSpeed(){ return speed; } - + // sets the parameter theta: // good parameters are in 1..3 // 0 = converge to pure conformal, ignore area preservation @@ -207,16 +207,16 @@ public: int GetTheta(){ return theta; } - + void IterateBlind(){ - /* todo: do as iterate, but without */ + /* todo: do as iterate, but without */ Iterate(); } - + ScalarType Iterate(){ - + ScalarType max; // max displacement - + #define v0 (f->V0(i)->T().P()) #define v1 (f->V1(i)->T().P()) #define v2 (f->V2(i)->T().P()) @@ -236,15 +236,15 @@ public: for (FaceIterator f=Super::m.face.begin(); f!=Super::m.face.end(); f++) { int i=0; ScalarType area2 = ((v1-v0) ^ (v2-v0)); for (i=0; i<3; i++){ - ScalarType + ScalarType a = (v1-v0).Norm(), b = ((v1-v0) * (v2-v0))/a, c = area2 / a, - + m0= data[f][i] / area2, m1= data[f][(i+1)%3] / area2, m2= data[f][(i+2)%3] / area2, - + mx= (b-a)/area2, my= c/area2, // 1.0/a mA= data[f][3]/area2 * scale, @@ -258,35 +258,35 @@ public: /* linear weightings - dx= (OMEGA) * (my * M2) + + dx= (OMEGA) * (my * M2) + (1-OMEGA) * ( px - 2.0*qx), - dy= (OMEGA) * (-mx * M2) + + dy= (OMEGA) * (-mx * M2) + (1-OMEGA) * ( py - 2.0*qy),*/ - + // exponential weighting // 2d gradient - + dx=// M1 - //*M1 // ^ theta-1 + //*M1 // ^ theta-1 pow(M1,theta-1) - *(px*(M1+ theta*M2) - 2.0*qx*M1), + *(px*(M1+ theta*M2) - 2.0*qx*M1), dy=// M1 - //*M1 // ^ theta-1 + //*M1 // ^ theta-1 pow(M1,theta-1) - *(py*(M1+ theta*M2) - 2.0*qy*M1), + *(py*(M1+ theta*M2) - 2.0*qy*M1), gy= dy/c, gx= (dx - gy*b) / a; // 3d gradient - sum[f->V(i)]+= ( (v1-v0) * gx + (v2-v0) * gy ) * data[f][3]; + sum[f->V(i)]+= ( (v1-v0) * gx + (v2-v0) * gy ) * data[f][3]; } } - max=0; // max displacement + max=0; // max displacement speed=0.001; - for (VertexIterator v=Super::m.vert.begin(); v!=Super::m.vert.end(); v++) - if ( !Super::isFixed[v] ) //if (!v->IsB()) + for (VertexIterator v=Super::m.vert.begin(); v!=Super::m.vert.end(); v++) + if ( !Super::isFixed[v] ) //if (!v->IsB()) { ScalarType n=sum[v].Norm(); if ( n > 1 ) { sum[v]/=n; n=1.0;} @@ -298,17 +298,17 @@ public: } return max; #undef v0 - #undef v1 - #undef v2 + #undef v1 + #undef v2 //printf("rejected %d\n",rejected); } - + void TargetCurrentGeometry(){ - + Super::isFixed.Start(); data.Start(); sum.Start(); - + totArea=0; for (FaceIterator f=Super::m.face.begin(); f!=Super::m.face.end(); f++) { double area2 = ((f->V(1)->P() - f->V(0)->P() )^(f->V(2)->P() - f->V(0)->P() )).Norm(); @@ -322,7 +322,7 @@ public: } } } - + }; @@ -333,12 +333,12 @@ public: // returns false if any fold is present (faster than MarkFolds) template bool IsFoldFree(MESH_TYPE &m){ - + assert(m.HasPerVertexTexture()); - + typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType; typedef typename MESH_TYPE::VertexType::TextureType::PointType::ScalarType ScalarType; - + ScalarType lastsign=0; for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){ ScalarType sign=((f->V(1)->T().P()-f->V(0)->T().P()) ^ (f->V(2)->T().P()-f->V(0)->T().P())); @@ -354,16 +354,16 @@ bool IsFoldFree(MESH_TYPE &m){ // returns number of folded faces template int MarkFolds(MESH_TYPE &m){ - + assert(m.HasPerVertexTexture()); assert(m.HasPerFaceQuality()); - + typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType; typedef typename MESH_TYPE::VertexType::TextureType::PointType::ScalarType ScalarType; - + SimpleTempData sign(m.face); sign.Start(0); - + // first pass, determine predominant sign int npos=0, nneg=0; ScalarType lastsign=0; @@ -372,7 +372,7 @@ int MarkFolds(MESH_TYPE &m){ if (fsign<0) { sign[f]=-1; nneg++; } if (fsign>0) { sign[f]=+1; npos++; } } - + // second pass, detect folded faces int res=0; short gsign= (nneg>npos)?-1:+1; @@ -382,28 +382,28 @@ int MarkFolds(MESH_TYPE &m){ f->Q()=0; } else f->Q()=1; } - + sign.Stop(); - + return res; } // Smooths texture coords. -// (can be useful to remove folds, +// (can be useful to remove folds, // e.g. these created when obtaining tecture coordinates after projections) template void SmoothTextureCoords(MESH_TYPE &m){ - + assert(m.HasPerVertexTexture()); - + typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType; - + SimpleTempData div(m.vert); SimpleTempData sum(m.vert); - + div.Start(); sum.Start(); - + for (typename MESH_TYPE::VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) { sum[v].SetZero(); div[v]=0; @@ -415,13 +415,13 @@ void SmoothTextureCoords(MESH_TYPE &m){ div[f->V(2)] +=2; sum[f->V(2)] += f->V(1)->T().P(); sum[f->V(2)] += f->V(0)->T().P(); } - for (typename MESH_TYPE::VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) // if (!v->IsB()) + for (typename MESH_TYPE::VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) // if (!v->IsB()) { if (v->div>0) { v->T().P() = sum[v]/div[v]; } } - + div.Stop(); sum.Stop(); diff --git a/vcg/math/matrix44.h b/vcg/math/matrix44.h index cb2f8c7c..11d228d9 100644 --- a/vcg/math/matrix44.h +++ b/vcg/math/matrix44.h @@ -566,7 +566,7 @@ bool Decompose(Matrix44 &M, Point3 &ScaleV, Point3 &ShearV, Point3 & return false; if(math::Abs(M.Determinant())<1e-10) return false; // matrix should be at least invertible... - // First Step recover the traslation + // First Step recover the translation TranV=M.GetColumn3(3); // Second Step Recover Scale and Shearing interleaved diff --git a/vcg/math/shot.h b/vcg/math/shot.h index 978100b2..0eeda9cf 100644 --- a/vcg/math/shot.h +++ b/vcg/math/shot.h @@ -207,7 +207,7 @@ public: } /* multiply the current reference frame for the matrix passed - note: it is up to the caller to check the the matrix passed is a pure rototraslation + note: it is up to the caller to check the the matrix passed is a pure rototranslation */ void MultMatrix( vcg::Matrix44 m44) { @@ -218,7 +218,7 @@ public: } /* multiply the current reference frame for the similarity passed - note: it is up to the caller to check the the matrix passed is a pure rototraslation + note: it is up to the caller to check the the matrix passed is a pure rototranslation */ void MultSimilarity( const Similarity & s){ MultMatrix(s.Matrix());} diff --git a/vcg/space/box.h b/vcg/space/box.h index ad4bdf97..8cc66abb 100644 --- a/vcg/space/box.h +++ b/vcg/space/box.h @@ -107,7 +107,7 @@ public: { return _min!=p._min || _max!=p._max; } - /** Infaltes the box of a percentage.. + /** Infltes the box of a percentage.. @param s Scalar value. E.g if s=0.1 the box enlarges of 10% in every direction if S==0.5 box doubles (+50% in every direction) if S < 0 box shrinks @@ -133,12 +133,12 @@ public: _min -= delta; _max += delta; } - /// Initializing the box + /// Initializing the box void Set( const PointType & p ) { _min = _max = p; } - /// Set the box to a null value + /// Set the box to a null value void SetNull() { _min.X()= 1; _max.X()= -1; @@ -147,7 +147,7 @@ public: } /** Add two boxex: Returns minimal box that contains both operands. - @param b The box to add + @param b The box to add */ void Add( Box const & b ) { @@ -174,7 +174,7 @@ public: }; } } - /** Coputes intersection of Boxes: the minimal box containing both operands. + /** Computes intersection of Boxes: the minimal box containing both operands. @param b The other operand */ void Intersect( const Box & b ) @@ -190,7 +190,7 @@ public: if(_min.X()>_max.X() || _min.Y()>_max.Y() ) SetNull(); else if (N>2) if (_min.Z()>_max.Z()) SetNull(); } - /** Traslalate the box. + /** Translalate the box. @param p: the translation vector */ void Translate( const PointType & p ) @@ -198,7 +198,7 @@ public: _min += p; _max += p; } - /** Check wheter a point is inside box. + /** Check whether a point is inside box. @param p The point @returns True if inside, false otherwise */ @@ -214,7 +214,7 @@ public: _min.Z() <= p.Z() && p.Z() <= _max.Z() ); } - /** Check wheter a point is inside box, open at left and closed at right [min..max) + /** Check whether a point is inside box, open at left and closed at right [min..max) @param p The point 3D @returns True if inside, false otherwise */ @@ -283,7 +283,7 @@ public: (p[2]-_min[2])/(_max[2]-_min[2]) ); } - /// Computes the Volume for the box. + /// Computes the Volume for the box. inline S Volume() const { if (N==2) return (_max.X()-_min.X())*(_max.Y()-_min.Y()); @@ -356,7 +356,7 @@ public: //@} //@{ - /** @name Iporters (for boxes in different spaces and with different scalar types) + /** @name Importers (for boxes in different spaces and with different scalar types) **/ /// imports the box diff --git a/vcg/space/box2.h b/vcg/space/box2.h index 651c903c..9f50e625 100644 --- a/vcg/space/box2.h +++ b/vcg/space/box2.h @@ -164,8 +164,8 @@ public: if(min.X()>max.X() || min.Y()>max.Y()) SetNull(); } - /** Traslate the bounding box by a vectore - @param p The transolation vector + /** Translate the bounding box by a vector + @param p The translation vector */ void Translate( const PointType & p ) { @@ -205,7 +205,7 @@ public: bb.Intersect(b); return bb.IsValid(); } - /** Check if emptry. + /** Check if empty. @return True iff empty */ inline bool IsNull() const { return min.X()>max.X() || min.Y()>max.Y(); } @@ -215,7 +215,7 @@ public: */ inline bool IsValid() const { return min.X()& leftHorizon() { return mLeftHorizon; } vcg::Point2i& size() { return mSize; } - //returns the score relative to the left horizon of that poly in that particular position, taking into account the choosen algo + //returns the score relative to the left horizon of that poly in that particular position, taking into account the chosen algo int getCostX(RasterizedOutline2& poly, Point2i pos, int rast_i) { switch (params.costFunction) { case CostFuncEnum::MinWastedSpace: return emptyCellBetweenPolyAndLeftHorizon(poly, pos, rast_i); @@ -315,7 +315,7 @@ public: return 0; } - //returns the score relative to the bottom horizon of that poly in that particular position, taking into account the choosen algo + //returns the score relative to the bottom horizon of that poly in that particular position, taking into account the chosen algo int getCostY(RasterizedOutline2& poly, Point2i pos, int rast_i) { switch (params.costFunction) { case CostFuncEnum::MinWastedSpace: return emptyCellBetweenPolyAndBottomHorizon(poly, pos, rast_i); diff --git a/vcg/space/ray2.h b/vcg/space/ray2.h index fb8defe8..fe38ea93 100644 --- a/vcg/space/ray2.h +++ b/vcg/space/ray2.h @@ -109,7 +109,7 @@ public: { if (NORM) return ScalarType((p-_ori)*_dir); else return ScalarType((p-_ori)*_dir/_dir.SquaredNorm()); } - /// returns wheter this type is normalized or not + /// returns whether this type is normalized or not static bool IsNormalized() {return NORM;}; /// calculates the point of parameter t on the ray. inline PointType P( const ScalarType t ) const diff --git a/vcg/space/ray3.h b/vcg/space/ray3.h index dc76fc2b..b3b7c047 100644 --- a/vcg/space/ray3.h +++ b/vcg/space/ray3.h @@ -115,7 +115,7 @@ public: { if (NORM) return ScalarType((p-_ori).dot(_dir)); else return ScalarType((p-_ori).dot(_dir)/_dir.SquaredNorm()); } - /// returns wheter this type is normalized or not + /// returns whether this type is normalized or not static bool IsNormalized() {return NORM;}; /// calculates the point of parameter t on the ray. inline PointType P( const ScalarType t ) const diff --git a/wrap/gui/activecoordinateframe.cpp b/wrap/gui/activecoordinateframe.cpp index 9891d18e..a3f65db7 100644 --- a/wrap/gui/activecoordinateframe.cpp +++ b/wrap/gui/activecoordinateframe.cpp @@ -68,16 +68,16 @@ void ActiveCoordinateFrame::Render(QGLWidget* glw) manipulator->center=position; manipulator->GetView(); manipulator->Apply(); - + MovableCoordinateFrame::Render(glw); - + // got nothing to draw if(!drawmoves && !drawrotations){ glPopMatrix(); - return; + return; } - int current_mode=manipulator->current_button; + int current_mode=manipulator->current_button; bool rotating=(current_mode==rotx)||(current_mode==roty)||(current_mode==rotz); bool moving=(current_mode==movx)||(current_mode==movy)||(current_mode==movz); @@ -89,18 +89,18 @@ void ActiveCoordinateFrame::Render(QGLWidget* glw) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); - + QString message("this should never be seen"); char axis_name; float verse; - + if(current_mode==x_modifier){ glColor(xcolor); message = QString("move or rotate on X axis"); } else if(current_mode==y_modifier){ glColor(ycolor); message = QString("move or rotate on Y axis"); } else if(current_mode==z_modifier){ glColor(zcolor); message = QString("move or rotate on Z axis"); - } else + } else if(rotating && drawrotations){ // draw a rotation Point3f axis, arc_point; float angle; @@ -126,15 +126,15 @@ void ActiveCoordinateFrame::Render(QGLWidget* glw) .arg(axis_name); Quaternionf arc_rot; arc_rot.FromAxis(angle/18.0,axis); - glBegin(GL_POLYGON); + glBegin(GL_POLYGON); glVertex(position); glVertex(position+arc_point); for(int i=0;i<18;i++){ arc_point = arc_rot.Rotate(arc_point); glVertex(position+arc_point); } - glEnd(); - } else if(moving && drawmoves){ // draw a traslation + glEnd(); + } else if(moving && drawmoves){ // draw a translation Point3f ntra=manipulator->track.tra; ntra.Normalize(); if(current_mode==movx){ @@ -159,11 +159,11 @@ void ActiveCoordinateFrame::Render(QGLWidget* glw) glEnd(); glBegin(GL_POINTS); glVertex(old_pos); - glEnd(); + glEnd(); } else { // got nothing to draw glPopAttrib(); glPopMatrix(); - return; + return; } // draw message below cursor font.setBold(true); @@ -179,7 +179,7 @@ void ActiveCoordinateFrame::Reset(bool reset_position,bool reset_alignment) { MovableCoordinateFrame::Reset(reset_position, reset_alignment); Update(); - manipulator->Reset(); + manipulator->Reset(); } void ActiveCoordinateFrame::SetPosition(const Point3f newpos) @@ -215,7 +215,7 @@ void ActiveCoordinateFrame::MouseMove(int x, int y) manipulator->MouseMove(x,y); } -void ActiveCoordinateFrame::MouseUp(int x, int y, /*Button */ int button) +void ActiveCoordinateFrame::MouseUp(int x, int y, /*Button */ int button) { Move(manipulator->track); manipulator->Reset(); @@ -263,9 +263,9 @@ void ActiveCoordinateFrame::Update() x_axis=r.Rotate(Point3f(1,0,0)); y_axis=r.Rotate(Point3f(0,1,0)); z_axis=r.Rotate(Point3f(0,0,1)); - + manipulator->ClearModes(); - manipulator->modes[0] = NULL; + manipulator->modes[0] = NULL; manipulator->modes[movx] = new AxisMode(p,x_axis); manipulator->modes[movy] = new AxisMode(p,y_axis); manipulator->modes[movz] = new AxisMode(p,z_axis); diff --git a/wrap/gui/activecoordinateframe.h b/wrap/gui/activecoordinateframe.h index d5a1dc8b..715fa3c2 100644 --- a/wrap/gui/activecoordinateframe.h +++ b/wrap/gui/activecoordinateframe.h @@ -87,7 +87,7 @@ public: @param new_rotation the new rotation of the coordinate frame. */ virtual void SetRotation(const Quaternionf rotation); - + /*! @brief Align the coordinate frame to one or two directions. @@ -99,8 +99,8 @@ public: @param primary the primary direction of alignment. @param secondary the secondary direction of alignment. - @param axis_1 the name of the axis to align to the primary direction, must be a char choosen from 'X', 'Y' and 'Z' - @param axis_2 the name of the axis to align to the secondary direction, must be different from axis_1 and must be a char choosen from 'X', 'Y', 'Z' and ' '; if the char is ' ' the axis is choosen automatically. + @param axis_1 the name of the axis to align to the primary direction, must be a char chosen from 'X', 'Y' and 'Z' + @param axis_2 the name of the axis to align to the secondary direction, must be different from axis_1 and must be a char chosen from 'X', 'Y', 'Z' and ' '; if the char is ' ' the axis is chosen automatically. */ virtual void AlignWith(const Point3f primary, const Point3f secondary, const char axis_1, const char axis_2); @@ -119,7 +119,7 @@ public: @param x the x coordinate of the cursor. @param y the y coordinate of the cursor. */ - void MouseMove(int x, int y); + void MouseMove(int x, int y); /*! @brief Interface function relative to mouse up event in QT. @@ -143,20 +143,20 @@ public: @param button the keyboard modifiers state. */ void ButtonDown(int button); - + /*! @brief Set rotational snap value. - + @param value the new rotational snap value, in degrees. */ void SetSnap(float value); /// The eulerian trackball. Trackball *manipulator; - + /// The flag that enables moves feedback rendering bool drawmoves; - + /// The flag that enables rotations feedback rendering bool drawrotations; protected: @@ -165,7 +165,7 @@ protected: const int x_modifier,y_modifier,z_modifier; Point3f x_axis,y_axis,z_axis; float rot_snap_rad,mov_snap; - // functions: + // functions: virtual void Move(const Similarityf); void Update(); private: diff --git a/wrap/gui/coordinateframe.h b/wrap/gui/coordinateframe.h index fb2098aa..56aa4256 100644 --- a/wrap/gui/coordinateframe.h +++ b/wrap/gui/coordinateframe.h @@ -212,8 +212,8 @@ public: @param primary the primary direction of alignment. @param secondary the secondary direction of alignment. - @param axis_1 the name of the axis to align to the primary direction, must be a char choosen from 'X', 'Y' and 'Z' - @param axis_2 the name of the axis to align to the secondary direction, must be different from axis_1 and must be a char choosen from 'X', 'Y', 'Z' and ' '; if the char is ' ' the axis is choosen automatically. + @param axis_1 the name of the axis to align to the primary direction, must be a char chosen from 'X', 'Y' and 'Z' + @param axis_2 the name of the axis to align to the secondary direction, must be different from axis_1 and must be a char chosen from 'X', 'Y', 'Z' and ' '; if the char is ' ' the axis is chosen automatically. */ virtual void AlignWith(const Point3f primary, const Point3f secondary, const char axis_1, const char axis_2); diff --git a/wrap/gui/trackball.h b/wrap/gui/trackball.h index 9d3a87f2..9b43e175 100644 --- a/wrap/gui/trackball.h +++ b/wrap/gui/trackball.h @@ -110,9 +110,9 @@ public: /// A trackball stores a transformation called 'track' that effectively rototranslate the object. Similarityf track; /// track position in model space. - Point3f center; + Point3f center; /// size of the widget in model space. - float radius; + float radius; }; /*! @@ -160,7 +160,7 @@ mesh->Render(); Note on the typical use: - - Perspective and glulookat are choosed to frame the origin centered 1-radius trackball. + - Perspective and glulookat are chosen to frame the origin centered 1-radius trackball. - The final scale and translate are just to fit a generic mesh to the 1sized origin centered where the trackball stays box. - The trackball works also on Orthographic projections \b but that are not centered around origin (just move it back along the Z) */ @@ -199,7 +199,7 @@ public: @warning The destructor does not deallocate the memory allocated by setDefaultMapping(), because the application can change the modes map. This can lead to small memory leaks, so please explicitally delete any manipulator in the modes map if you are going to repeatly allocate and deallocate Trackball instances. */ ~Trackball(); - + private: // Trackball must not be copied. Use Append (see vcg/complex/trimesh/append.h) Trackball operator =(const Trackball & /*m*/) = delete; @@ -273,7 +273,7 @@ public: void ApplyInverse(); // DrawIcon() has been moved to trackutils.h //void DrawIcon(); - + // T(c) S R T(t) T(-c) => S R T(S^(-1) R^(-1)(c) + t - c) Matrix44f Matrix() const; Matrix44f InverseMatrix() const; @@ -315,7 +315,7 @@ public: @param x The horizontal coordinate of the mouse pointer. @param y The vertical coordinate of the mouse pointer. */ - void MouseMove(int x, int y); + void MouseMove(int x, int y); /*! @brief Interface function relative to mouse down event in QT/SDL. @@ -323,7 +323,7 @@ public: @param y The vertical coordinate of the mouse pointer. @param button The new state. */ - void MouseUp(int x, int y, /*Button */ int button); + void MouseUp(int x, int y, /*Button */ int button); /*! @brief Old interface function relative to mouse down event in QT/SDL. @@ -367,9 +367,9 @@ public: void SetSpinnable(bool on); - + // returns if it is animating or not - // + // bool IsAnimating(unsigned int msec=0); // Animate: either takes an absolute time (if default not specified, then it is automeasured) @@ -424,7 +424,7 @@ public: /* //internals // commented out no more used this stuff! enum Action { NONE = 0, VIEW_ROTATE = 1, - // Axis Constrained Rotation + // Axis Constrained Rotation TRACK_ROTATE_X = 3, TRACK_ROTATE_Y = 4, TRACK_ROTATE_Z = 5, // Drag constrained to an axis (trackball axis) DRAG_X = 6, DRAG_Y = 7, DRAG_Z = 8, @@ -469,9 +469,9 @@ public: /// The inactive manipulator. It is drawn when Trackball is inactive. TrackMode *inactive_mode; - + // The manipulator to deal with timer events and key events - TrackMode *idle_and_keys_mode; + TrackMode *idle_and_keys_mode; /*! @brief Reset modes to default mapping. @@ -493,7 +493,7 @@ public: /// Transformation before current user action. Similarityf last_track; /// track after an Undo() call. - Similarityf undo_track; + Similarityf undo_track; /// Currently not in use. Similarityf last_view; /// Mouse cursor coordinates before current action. diff --git a/wrap/io_tetramesh/io_ply.h b/wrap/io_tetramesh/io_ply.h index c2e9d472..848e4e49 100644 --- a/wrap/io_tetramesh/io_ply.h +++ b/wrap/io_tetramesh/io_ply.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -52,9 +52,9 @@ namespace vcg { namespace tetra { namespace io { - + /** Additional data needed or useful for parsing a ply mesh. -This class can be passed to the ImporterPLY::Open() function for +This class can be passed to the ImporterPLY::Open() function for - retrieving additional per-vertex per-tetra data - specifying a callback for long ply parsing - knowing what data is contained in a ply file @@ -74,10 +74,10 @@ public: } /// Store the error codes enconutered when parsing a ply int status; - /// It returns a bit mask describing the field preesnt in the ply file - int mask; + /// It returns a bit mask describing the field present in the ply file + int mask; - /// a Simple callback that can be used for long ply parsing. + /// a Simple callback that can be used for long ply parsing. // it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...) CallBackPos *cb; @@ -87,7 +87,7 @@ public: PropDescriptor *VertexData; /// the number of per-face descriptor (usually 0) int fdn; - + /// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply PropDescriptor *TetraData; diff --git a/wrap/io_trimesh/import_ptx.h b/wrap/io_trimesh/import_ptx.h index f049d398..79a43960 100644 --- a/wrap/io_trimesh/import_ptx.h +++ b/wrap/io_trimesh/import_ptx.h @@ -67,7 +67,7 @@ public: flipfaces = false; } - /// a bit mask describing the field preesnt in the ply file + /// a bit mask describing the field present in the ply file int mask; /// index of mesh to be imported @@ -189,8 +189,8 @@ public: if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false; // initial 4 lines - if (!fscanf(fp, "%lf %lf %lf\n", &xx, &yy, &zz)) return false; // scanner registered position - if (!fscanf(fp, "%lf %lf %lf\n", &xx, &yy, &zz)) return false; // scanner registered axis 'X' + if (!fscanf(fp, "%lf %lf %lf\n", &xx, &yy, &zz)) return false; // scanner registered position + if (!fscanf(fp, "%lf %lf %lf\n", &xx, &yy, &zz)) return false; // scanner registered axis 'X' if (!fscanf(fp, "%lf %lf %lf\n", &xx, &yy, &zz)) return false; // scanner registered axis 'Y' if (!fscanf(fp, "%lf %lf %lf\n", &xx, &yy, &zz)) return false; // scanner registered axis 'Z' // now the transformation matrix @@ -434,7 +434,7 @@ public: tri::Clean::RemoveUnreferencedVertex(m); } } - Matrix44x tr; + Matrix44x tr; tr.Import(currtrasf); tri::UpdatePosition::Matrix(m,tr,true); tri::Allocator::CompactVertexVector(m); diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index 5a504784..f52547e8 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -54,9 +54,9 @@ namespace io { - + /** Additional data needed or useful for parsing a ply mesh. -This class can be passed to the ImporterPLY::Open() function for +This class can be passed to the ImporterPLY::Open() function for - retrieving additional per-vertex per-face data - specifying a callback for long ply parsing - knowing what data is contained in a ply file @@ -65,13 +65,13 @@ class PlyInfo { public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; - + void AddPerElemFloatAttribute(int elemType, const char *attrName, const char * propName=0) { static const char *elemStr[2]={"vertex","face"}; std::vector *elemDescVec[2]={&(this->VertDescriptorVec), &(this->FaceDescriptorVec)}; std::vector *elemNameVec[2]={&(this->VertAttrNameVec), &(this->FaceAttrNameVec)}; - + if(propName==0) propName=attrName; elemDescVec[elemType]->push_back(PropDescriptor()); elemNameVec[elemType]->push_back(attrName); @@ -80,71 +80,71 @@ public: elemDescVec[elemType]->back().stotype1 = vcg::ply::T_FLOAT; elemDescVec[elemType]->back().memtype1 = vcg::ply::T_FLOAT; } - - void AddPerVertexFloatAttribute(const char *attrName, const char *propName=0) { - AddPerElemFloatAttribute(0,attrName,propName); + + void AddPerVertexFloatAttribute(const char *attrName, const char *propName=0) { + AddPerElemFloatAttribute(0,attrName,propName); } - void AddPerFaceFloatAttribute(const char *attrName, const char *propName=0) { - AddPerElemFloatAttribute(1,attrName,propName); + void AddPerFaceFloatAttribute(const char *attrName, const char *propName=0) { + AddPerElemFloatAttribute(1,attrName,propName); } - - - /* Note that saving a per vertex point3 attribute is a mess. + + + /* Note that saving a per vertex point3 attribute is a mess. * Actually require to allocate 3 float attribute and save them. And they are never deallocated... */ template void AddPerVertexPoint3fAttribute(MeshType &m, const char *attrName, const char *propName="") { if(propName==0) propName=attrName; - + const char *attrxyz[3] = { strdup((std::string(attrName)+std::string("_x")).c_str()), strdup((std::string(attrName)+std::string("_y")).c_str()), strdup((std::string(attrName)+std::string("_z")).c_str()), }; - typename MeshType::template PerVertexAttributeHandle + typename MeshType::template PerVertexAttributeHandle ht = vcg::tri::Allocator:: template GetPerVertexAttribute (m,attrName); - + typename MeshType::template PerVertexAttributeHandle htt[3]; - + for(int i=0;i<3;++i) - { + { htt[i] = vcg::tri::Allocator:: template GetPerVertexAttribute (m,std::string(attrxyz[i])); // ForEachVertex (m, [&](typename MeshType::VertexType &v) { // htt[i][v] = ht[v][i]; -// }); +// }); for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) - if(!vi->IsD()) + if(!vi->IsD()) htt[i][vi] = ht[vi][i]; - AddPerVertexFloatAttribute(attrxyz[i]); + AddPerVertexFloatAttribute(attrxyz[i]); } } - - + + PlyInfo() { status=0; mask=0; - cb=0; + cb=0; } /// Store the error codes enconutered when parsing a ply int status; - /// It returns a bit mask describing the field preesnt in the ply file - int mask; + /// It returns a bit mask describing the field present in the ply file + int mask; - /// a Simple callback that can be used for long ply parsing. + /// a Simple callback that can be used for long ply parsing. // it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...) CallBackPos *cb; /// The additional vertex descriptor that a user can specify to load additional per-vertex non-standard data stored in a ply std::vector VertDescriptorVec; - /// AttributeName is an array, externally allocated, containing the names of the attributes to be saved (loaded). + /// AttributeName is an array, externally allocated, containing the names of the attributes to be saved (loaded). /// We assume that AttributeName[], if not empty, is exactly of the same size of VertexdData[] /// If AttributeName[i] is not empty we use it to retrieve/store the info instead of the offsetted space in the current vertex - std::vector VertAttrNameVec; - + std::vector VertAttrNameVec; + /// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply std::vector FaceDescriptorVec; - std::vector FaceAttrNameVec; + std::vector FaceAttrNameVec; /// a string containing the current ply header. Useful for showing it to the user. std::string header; diff --git a/wrap/math/sparse_matrix.h b/wrap/math/sparse_matrix.h index cef43843..802c6ad9 100644 --- a/wrap/math/sparse_matrix.h +++ b/wrap/math/sparse_matrix.h @@ -15,10 +15,10 @@ public: std::vector _Ap; std::vector _Ai; std::vector _Ax; - + typedef typename std::pair IndexType; - - int _dimension; + + int _dimension; public: @@ -26,16 +26,16 @@ public: virtual void Initalize(int dimension) {_dimension=dimension;} -///create a sparse matrix given a set of entries as vector +///create a sparse matrix given a set of entries as vector ///of pair of int virtual void CreateSparse(std::vector Entries) {} -///return the value of the matrix +///return the value of the matrix virtual ScalarType &A(int row,int col) {return (_Ax[0]);} -///return true if the rapresention of sparse matriz is symmetric +///return true if the represention of sparse matriz is symmetric virtual bool IsSymmetric() {return false;} @@ -45,4 +45,4 @@ virtual void Zero() ///return the dimension of the matrix virtual int Size(){return _dimension;} -}; \ No newline at end of file +}; From 045d13add4d981e596e6546c020941517ddc5c33 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 25 Mar 2021 15:29:38 +0100 Subject: [PATCH 099/140] ghactions builds examples from cmake --- .../{BuildSamplesUbuntu.yml => BuildExamplesLinux.yml} | 10 ++++++---- .../{BuildSamplesMacOS.yml => BuildExamplesMacOS.yml} | 8 +++++--- ...uildSamplesWindows.yml => BuildExamplesWindows.yml} | 8 +++++--- 3 files changed, 16 insertions(+), 10 deletions(-) rename .github/workflows/{BuildSamplesUbuntu.yml => BuildExamplesLinux.yml} (55%) rename .github/workflows/{BuildSamplesMacOS.yml => BuildExamplesMacOS.yml} (64%) rename .github/workflows/{BuildSamplesWindows.yml => BuildExamplesWindows.yml} (84%) diff --git a/.github/workflows/BuildSamplesUbuntu.yml b/.github/workflows/BuildExamplesLinux.yml similarity index 55% rename from .github/workflows/BuildSamplesUbuntu.yml rename to .github/workflows/BuildExamplesLinux.yml index 9601bba4..e2fa3b37 100644 --- a/.github/workflows/BuildSamplesUbuntu.yml +++ b/.github/workflows/BuildExamplesLinux.yml @@ -1,12 +1,12 @@ -name: BuildSamplesUbuntu +name: BuildExamplesLinux on: [push, pull_request] jobs: ubuntu_build_tests: - name: Build Samples (Ubuntu) - runs-on: ubuntu-latest #in order to deploy, need to use oldest supported version + name: Build Examples (Linux) + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -14,5 +14,7 @@ jobs: uses: jurplel/install-qt-action@v2 - name: Build Samples run: | - qmake apps/sample/sample.pro + mkdir build + cd build + cmake -DVCG_BUILD_EXAMPLES=ON .. make -j4 diff --git a/.github/workflows/BuildSamplesMacOS.yml b/.github/workflows/BuildExamplesMacOS.yml similarity index 64% rename from .github/workflows/BuildSamplesMacOS.yml rename to .github/workflows/BuildExamplesMacOS.yml index 7640a8ea..1c86276f 100644 --- a/.github/workflows/BuildSamplesMacOS.yml +++ b/.github/workflows/BuildExamplesMacOS.yml @@ -1,11 +1,11 @@ -name: BuildSamplesMacOS +name: BuildExamplesMacOS on: [push, pull_request] jobs: macos_build_tests: - name: Build Samples (MacOS) + name: Build Examples (MacOS) runs-on: macos-latest steps: @@ -14,5 +14,7 @@ jobs: uses: jurplel/install-qt-action@v2 - name: Build Samples run: | - qmake apps/sample/sample.pro + mkdir build + cd build + cmake -DVCG_BUILD_EXAMPLES=ON .. make -j4 diff --git a/.github/workflows/BuildSamplesWindows.yml b/.github/workflows/BuildExamplesWindows.yml similarity index 84% rename from .github/workflows/BuildSamplesWindows.yml rename to .github/workflows/BuildExamplesWindows.yml index a9a069b0..f92285cc 100644 --- a/.github/workflows/BuildSamplesWindows.yml +++ b/.github/workflows/BuildExamplesWindows.yml @@ -1,10 +1,10 @@ -name: BuildSamplesWindows +name: BuildExamplesWindows on: [push, pull_request] jobs: windows_build_tests: - name: Build Samples (Windows) + name: Build Examples (Windows) runs-on: windows-latest steps: @@ -25,5 +25,7 @@ jobs: uses: jurplel/install-qt-action@v2 - name: Build Samples run: | - qmake apps/sample/sample.pro + mkdir build + cd build + cmake -G "NMake Makefiles" -DVCG_BUILD_EXAMPLES=ON .. jom -j4 From eed785fdd35cc3cd9438022d52681606b4e4457c Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 25 Mar 2021 15:39:09 +0100 Subject: [PATCH 100/140] update readme --- README.md | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 63209851..e65a1b39 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ The **_Visualization and Computer Graphics Library_** (VCGlib for short) is a open source, portable, C++, templated, no dependency, library for manipulation, processing, cleaning, simplifying triangle meshes. -![BuildSamplesUbuntu](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildSamplesUbuntu/badge.svg) -![BuildSamplesMacOS](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildSamplesMacOS/badge.svg) -![BuildSamplesWindows](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildSamplesWindows/badge.svg) +![BuilExamplesLinux](https://github.com/cnr-isti-vclab/vcglib/workflows/BuilExamplesLinux/badge.svg) +![BuildExamplesMacOS](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesMacOS/badge.svg) +![BuildExamplesWindows](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesWindows/badge.svg) The library, composed by more than 100k lines of code, is released under the GPL license, and it is the base of most of the software tools of the [Visual Computing Lab](http://vcg.isti.cnr.it) of the Italian National Research Council Institute ISTI, like MeshLab, metro and many others. @@ -28,17 +28,10 @@ A number of applications have been developed using the vcglib: - Metro, the tool for measuring differences between meshes - The first high quality out-of-core mesh simplifier that was used by the Stanford Digital Michelangelo project to process their huge 3D scanned models. -## Contributing -In case of bugs please report them [here](https://github.com/cnr-isti-vclab/vcglib/issues). - -Copyright of the library is fully owned by CNR. Contributing means signing an appropriate [license agreement](https://github.com/cnr-isti-vclab/vcglib/blob/master/docs/ContributorLicenseAgreement.pdf) . - -Pull requests about trivial, small, questionable updates (e.g. small stylistic changes like int -> uint8_t) will be rejected without discussion. - - ## Contacts For any info about licensing (portion of) the library please contact us: Paolo Cignoni (p.cignoni@isti.cnr.it) Visual Computing Lab of the Italian National Research Council - ISTI +In case of bugs please report them [here](https://github.com/cnr-isti-vclab/vcglib/issues) . From c8149ca991d7f10f936631b52004bbeb8abdb6bd Mon Sep 17 00:00:00 2001 From: Alessandro Muntoni Date: Thu, 25 Mar 2021 15:39:59 +0100 Subject: [PATCH 101/140] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e65a1b39..d98ee6ec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ The **_Visualization and Computer Graphics Library_** (VCGlib for short) is a open source, portable, C++, templated, no dependency, library for manipulation, processing, cleaning, simplifying triangle meshes. -![BuilExamplesLinux](https://github.com/cnr-isti-vclab/vcglib/workflows/BuilExamplesLinux/badge.svg) +![BuildExamplesLinux](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesLinux/badge.svg) ![BuildExamplesMacOS](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesMacOS/badge.svg) ![BuildExamplesWindows](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesWindows/badge.svg) From ade2c49443beee39ddc3cd70f1d2172d550f7f03 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 25 Mar 2021 18:13:41 +0100 Subject: [PATCH 102/140] some cleanups --- vcg/complex/base.h | 4 +- vcg/space/box.h | 2 +- vcg/space/box2.h | 285 +++++++++++++++++----------------- vcg/space/box3.h | 52 +++---- vcg/space/deprecated_point3.h | 2 +- vcg/space/deprecated_point4.h | 6 +- vcg/space/line2.h | 2 +- 7 files changed, 178 insertions(+), 175 deletions(-) diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 4a1e01f9..88de7028 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -25,6 +25,8 @@ #define __VCG_COMPLEX_BASE #include +#include + #include #include "used_types.h" @@ -599,7 +601,7 @@ template inline bool IsMarked(const MeshType & m,typename MeshT @param m the mesh containing the element @param t tetra pointer */ template -inline bool IsMarked(MeshType &m, typename MeshType::ConstTetraPointer t) { return t->cIMark() == m.imark; } +inline bool IsMarked(const MeshType &m, typename MeshType::ConstTetraPointer t) { return t->cIMark() == m.imark; } /** \brief Set the vertex incremental mark of the vertex to the one of the mesh. @param m the mesh containing the element diff --git a/vcg/space/box.h b/vcg/space/box.h index 8cc66abb..2cb77ab1 100644 --- a/vcg/space/box.h +++ b/vcg/space/box.h @@ -49,7 +49,7 @@ First working release. #ifndef __VCGLIB_BOX #define __VCGLIB_BOX -#include +#include #include #include diff --git a/vcg/space/box2.h b/vcg/space/box2.h index 9f50e625..ad0a5854 100644 --- a/vcg/space/box2.h +++ b/vcg/space/box2.h @@ -2,7 +2,7 @@ * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004-2016 \/)\/ * +* Copyright(C) 2004-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -36,54 +36,51 @@ template class Segment2; /** \addtogroup space */ /*@{*/ /** - Templated class for a 2D bounding box. It is stored just as two Point2 + Templated class for a 2D bounding box. It is stored just as two Point2 @param BoxScalarType (Template Parameter) Specifies the scalar field. */ template class Box2 { public: - /// The scalar type + /// The scalar type typedef BoxScalarType ScalarType; - typedef Point2 PointType ; + typedef Point2 PointType; - /// min coordinate point - PointType min; - /// max coordinate point - PointType max; - /// Standard constructor + /// min coordinate point + PointType min; + /// max coordinate point + PointType max; + /// Standard constructor inline Box2() { min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; } - /// Copy constructor - inline Box2( const Box2 & b ) { min=b.min; max=b.max; } - /// Min Max constructor - inline Box2( const Point2 & mi, const Point2 & ma ) { min = mi; max = ma; } + /// Min Max constructor + inline Box2(const Point2 & mi, const Point2 & ma ) { min = mi; max = ma; } - inline Box2(const Point2 & center, const BoxScalarType & radius) { - min = center-Point2(radius,radius); - max = center+Point2(radius,radius); - } + inline Box2(const Point2 & center, const BoxScalarType & radius) + { + min = center-Point2(radius,radius); + max = center+Point2(radius,radius); + } - /// Distructor - inline ~Box2() { } - /// Operator to compare two bounding box + /// Operator to compare two bounding box inline bool operator == ( Box2 const & p ) const { return min==p.min && max==p.max; } - /// Initializing the bounding box with a point + /// Initializing the bounding box with a point void Set( const PointType & p ) { min = max = p; } - Point2 P(const int & i) const + Point2 P(int i) const { - return Point2( - min[0]+ (i%2) * DimX(), + return Point2( + min[0]+ (i%2) * DimX(), min[1]+ ((i / 2)%2) * DimY()); } - // Initializing with the values + // Initializing with the values inline void Set( ScalarType minx, ScalarType miny, ScalarType maxx, ScalarType maxy ) { min[0] = minx; @@ -91,15 +88,15 @@ public: max[0] = maxx; max[1] = maxy; } - /// Set the bounding box to a null value + /// Set the bounding box to a null value void SetNull() { - min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; + min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; } - /** Function to add two bounding box - the bounding box expand to include the other bounding box (if necessary) - @param b The bounding box to be added - */ + /** @brief Function to add two bounding box + * the bounding box expand to include the other bounding box (if necessary) + * @param b The bounding box to be added + */ void Add( Box2 const & b ) { if(IsNull()) @@ -116,14 +113,15 @@ public: if(max.Y() < b.max.Y()) max.Y() = b.max.Y(); } } - /** Adds a point to the bouning box. - the bounding box expand to include the new point (if necessary) - @param p The point 2D - */ + /** + * @brief Adds a point to the bouning box. + * the bounding box expand to include the new point (if necessary) + * @param p The point 2D + */ void Add( const PointType & p ) { if(IsNull()) Set(p); - else + else { if(min.X() > p.X()) min.X() = p.X(); if(min.Y() > p.Y()) min.Y() = p.Y(); @@ -133,26 +131,29 @@ public: } } - /** Varies the dimension of the bounding box. - @param delta The size delta (if positive, box is enlarged) - */ - void Offset(const ScalarType s) + /** + * @brief Varies the dimension of the bounding box. + * @param delta The size delta (if positive, box is enlarged) + */ + void Offset(ScalarType s) { Offset(PointType(s, s)); } - /** Varies the dimension of the bounding box. - @param delta The size delta per dimension (if positive, box is enlarged) - */ + /** + * @brief Varies the dimension of the bounding box. + * @param delta The size delta per dimension (if positive, box is enlarged) + */ void Offset(const PointType & delta) { min -= delta; max += delta; } - /** Computes intersection between this and another bounding box - @param b The other bounding box - */ + /** + * @brief Computes intersection between this and another bounding box + * @param b The other bounding box + */ void Intersect( const Box2 & b ) { if(min.X() < b.min.X()) min.X() = b.min.X(); @@ -164,114 +165,118 @@ public: if(min.X()>max.X() || min.Y()>max.Y()) SetNull(); } - /** Translate the bounding box by a vector - @param p The translation vector - */ + /** + * @brief Translate the bounding box by a vector + * @param p The translation vector + */ void Translate( const PointType & p ) { min += p; max += p; } - /** Checks whether a 2D point p is inside the box - @param p The point 2D - @return True iff p inside - */ - bool IsIn( PointType const & p ) const + /** + * @brief Checks whether a 2D point p is inside the box + * @param p The point 2D + * @return True iff p inside + */ + bool IsIn( const PointType & p ) const { return ( min.X() <= p.X() && p.X() <= max.X() && - min.Y() <= p.Y() && p.Y() <= max.Y() - ); + min.Y() <= p.Y() && p.Y() <= max.Y()); } - /** Checks whether a 2D point p is inside the box, closed at min but open at max - @param p The point in 2D - @return True iff p inside - */ - bool IsInEx( PointType const & p ) const + /** + * @brief Checks whether a 2D point p is inside the box, closed at min but open at max + * @param p The point in 2D + * @return True iff p inside + */ + bool IsInEx( const PointType & p ) const { - return ( + return ( min.X() <= p.X() && p.X() < max.X() && - min.Y() <= p.Y() && p.Y() < max.Y() - ); + min.Y() <= p.Y() && p.Y() < max.Y()); } - /** Check bbox collision. - Note: just adjiacent bbox won't collide - @param b A bounding box - @return True iff collision - */ - bool Collide( Box2 const &b ) + /** + * @brief Check bbox collision. + * Note: just adjiacent bbox won't collide + * @param b A bounding box + * @return True iff collision + */ + bool Collide( const Box2 &b ) const { Box2 bb=*this; bb.Intersect(b); return bb.IsValid(); } - /** Check if empty. - @return True iff empty - */ + /** + * Check if empty. + * @return True iff empty + */ inline bool IsNull() const { return min.X()>max.X() || min.Y()>max.Y(); } - /** Check consistency. - @return True iff consistent - */ + /** + * Check consistency. + * @return True iff consistent + */ inline bool IsValid() const { return min.X() @@ -300,36 +305,36 @@ ScalarType DistancePoint2Box2(const Point2 &test, if ((test.X()<=bbox.min.X())&&(test.Y()<=bbox.min.Y())) return ((test-bbox.min).Norm()); else - if ((test.X()>=bbox.min.X())&& - (test.X()<=bbox.max.X())&& - (test.Y()<=bbox.min.Y())) - return (bbox.min.Y()-test.Y()); - else - if ((test.X()>=bbox.max.X())&& - (test.Y()<=bbox.min.Y())) - return ((test-vcg::Point2(bbox.max.X(),bbox.min.Y())).Norm()); - else - if ((test.Y()>=bbox.min.Y())&& - (test.Y()<=bbox.max.Y())&& - (test.X()>=bbox.max.X())) - return (test.X()-bbox.max.X()); - else - if ((test.X()>=bbox.max.X())&&(test.Y()>=bbox.max.Y())) - return ((test-bbox.max).Norm()); - else - if ((test.X()>=bbox.min.X())&& - (test.X()<=bbox.max.X())&& - (test.Y()>=bbox.max.Y())) - return (test.Y()-bbox.max.Y()); - else - if ((test.X()<=bbox.min.X())&& - (test.Y()>=bbox.max.Y())) - return ((test-vcg::Point2(bbox.min.X(),bbox.max.Y())).Norm()); - else - if ((test.X()<=bbox.min.X())&& - (test.Y()<=bbox.max.Y())&& - (test.Y()>=bbox.min.Y())) - return (bbox.min.X()-test.X()); + if ((test.X()>=bbox.min.X())&& + (test.X()<=bbox.max.X())&& + (test.Y()<=bbox.min.Y())) + return (bbox.min.Y()-test.Y()); + else + if ((test.X()>=bbox.max.X())&& + (test.Y()<=bbox.min.Y())) + return ((test-vcg::Point2(bbox.max.X(),bbox.min.Y())).Norm()); + else + if ((test.Y()>=bbox.min.Y())&& + (test.Y()<=bbox.max.Y())&& + (test.X()>=bbox.max.X())) + return (test.X()-bbox.max.X()); + else + if ((test.X()>=bbox.max.X())&&(test.Y()>=bbox.max.Y())) + return ((test-bbox.max).Norm()); + else + if ((test.X()>=bbox.min.X())&& + (test.X()<=bbox.max.X())&& + (test.Y()>=bbox.max.Y())) + return (test.Y()-bbox.max.Y()); + else + if ((test.X()<=bbox.min.X())&& + (test.Y()>=bbox.max.Y())) + return ((test-vcg::Point2(bbox.min.X(),bbox.max.Y())).Norm()); + else + if ((test.X()<=bbox.min.X())&& + (test.Y()<=bbox.max.Y())&& + (test.Y()>=bbox.min.Y())) + return (bbox.min.X()-test.X()); } else { @@ -372,13 +377,13 @@ Point2 ClosestPoint2Box2(const Point2 &test, return closest; } - /// Specificazione di box of short +/// Specificazione di box of short typedef Box2 Box2s; - /// Specificazione di box of int +/// Specificazione di box of int typedef Box2 Box2i; - /// Specificazione di box of float +/// Specificazione di box of float typedef Box2 Box2f; - /// Specificazione di box of double +/// Specificazione di box of double typedef Box2 Box2d; /*@}*/ diff --git a/vcg/space/box3.h b/vcg/space/box3.h index 4fd6de3a..862767db 100644 --- a/vcg/space/box3.h +++ b/vcg/space/box3.h @@ -46,29 +46,27 @@ public: typedef BoxScalarType ScalarType; /// min coordinate point - Point3 min; + Point3 min; /// max coordinate point Point3 max; /// The bounding box constructor inline Box3() { this->SetNull(); } - /// Copy constructor - //inline Box3( const Box3 & b ) { min=b.min; max=b.max; } /// Min Max constructor inline Box3( const Point3 & mi, const Point3 & ma ) { min = mi; max = ma; } /// Point Radius Constructor - inline Box3(const Point3 & center, const BoxScalarType & radius) { - min = center-Point3(radius,radius,radius); - max = center+Point3(radius,radius,radius); - } + inline Box3(const Point3 & center, const BoxScalarType & radius) { + min = center-Point3(radius,radius,radius); + max = center+Point3(radius,radius,radius); + } /// The bounding box distructor inline ~Box3() { } /// Operator to compare two bounding box - inline bool operator == ( Box3 const & p ) const + inline bool operator == ( const Box3 & p ) const { return min==p.min && max==p.max; } /// Operator to dispare two bounding box - inline bool operator != ( Box3 const & p ) const + inline bool operator != ( const Box3 & p ) const { return min!=p.min || max!=p.max; } @@ -103,7 +101,7 @@ public: /** Modify the current bbox to contain also the passed box. * Adding a null bounding box does nothing */ - void Add( Box3 const & b ) + void Add( const Box3 & b ) { if(b.IsNull()) return; // Adding a null bbox should do nothing if(IsNull()) *this=b; @@ -137,20 +135,20 @@ public: /** Modify the current bbox to contain also the passed sphere */ -void Add( const Point3 & p, const BoxScalarType radius ) -{ - if(IsNull()) Set(p); - else + void Add( const Point3 & p, const BoxScalarType radius ) { - min.X() = std::min(min.X(),p.X()-radius); - min.Y() = std::min(min.Y(),p.Y()-radius); - min.Z() = std::min(min.Z(),p.Z()-radius); + if(IsNull()) Set(p); + else + { + min.X() = std::min(min.X(),p.X()-radius); + min.Y() = std::min(min.Y(),p.Y()-radius); + min.Z() = std::min(min.Z(),p.Z()-radius); - max.X() = std::max(max.X(),p.X()+radius); - max.Y() = std::max(max.Y(),p.Y()+radius); - max.Z() = std::max(max.Z(),p.Z()+radius); + max.X() = std::max(max.X(),p.X()+radius); + max.Y() = std::max(max.Y(),p.Y()+radius); + max.Z() = std::max(max.Z(),p.Z()+radius); + } } -} /** Modify the current bbox to contain also the box b transformed according to the matrix m */ void Add( const Matrix44 &m, const Box3 & b ) @@ -193,7 +191,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) } /** true if the point belong to the closed box */ - bool IsIn( Point3 const & p ) const + bool IsIn( const Point3 & p ) const { return ( min.X() <= p.X() && p.X() <= max.X() && @@ -204,7 +202,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) /** true if the point belong to the open box (open on the max side) * e.g. if p in [min,max) */ - bool IsInEx( Point3 const & p ) const + bool IsInEx( const Point3 & p ) const { return ( min.X() <= p.X() && p.X() < max.X() && @@ -225,7 +223,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) return bb.IsValid(); } */ - bool Collide(Box3 const &b) const + bool Collide( const Box3 &b) const { return b.min.X()min.X() && b.min.Y()min.Y() && @@ -259,14 +257,14 @@ void Add( const Point3 & p, const BoxScalarType radius ) return (max-min); } /// Returns global coords of a local point expressed in [0..1]^3 - Point3 LocalToGlobal(Point3 const & p) const{ + Point3 LocalToGlobal(const Point3 & p) const{ return Point3( min[0] + p[0]*(max[0]-min[0]), min[1] + p[1]*(max[1]-min[1]), min[2] + p[2]*(max[2]-min[2])); } /// Returns local coords expressed in [0..1]^3 of a point in 3D - Point3 GlobalToLocal(Point3 const & p) const{ + Point3 GlobalToLocal(const Point3 & p) const{ return Point3( (p[0]-min[0])/(max[0]-min[0]), (p[1]-min[1])/(max[1]-min[1]), @@ -313,7 +311,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) } /// gives the ith box vertex in order: (x,y,z),(X,y,z),(x,Y,z),(X,Y,z),(x,y,Z),(X,y,Z),(x,Y,Z),(X,Y,Z) - Point3 P(const int & i) const { + Point3 P(int i) const { return Point3( min[0]+ (i%2) * DimX(), min[1]+ ((i / 2)%2) * DimY(), diff --git a/vcg/space/deprecated_point3.h b/vcg/space/deprecated_point3.h index dd32ebfd..a5e75494 100644 --- a/vcg/space/deprecated_point3.h +++ b/vcg/space/deprecated_point3.h @@ -253,7 +253,7 @@ public: assert(i>=0 && i<3); return _v[i]; } - inline const P3ScalarType &X() const { return _v[0]; } + inline const P3ScalarType &X() const { return _v[0]; } inline const P3ScalarType &Y() const { return _v[1]; } inline const P3ScalarType &Z() const { return _v[2]; } inline P3ScalarType &X() { return _v[0]; } diff --git a/vcg/space/deprecated_point4.h b/vcg/space/deprecated_point4.h index a932f43d..39b5d135 100644 --- a/vcg/space/deprecated_point4.h +++ b/vcg/space/deprecated_point4.h @@ -97,10 +97,8 @@ public: { _v[0] = p[0]; _v[1]= p[1]; _v[2] = p[2]; _v[3]= p[3]; } - inline Point4 ( const Point4 & p ) - { - _v[0]= p._v[0]; _v[1]= p._v[1]; _v[2]= p._v[2]; _v[3]= p._v[3]; - } + inline Point4 ( const Point4 & p ) = default; + inline void SetZero() { _v[0] = _v[1] = _v[2] = _v[3]= 0; diff --git a/vcg/space/line2.h b/vcg/space/line2.h index 2abeb18d..68314006 100644 --- a/vcg/space/line2.h +++ b/vcg/space/line2.h @@ -167,7 +167,7 @@ public: Line2 (const Line2 &r) { Import(r); }; /// assignment - inline LineType & operator = ( Line2 const &r) + inline LineType & operator = ( const Line2 &r) { Import(r); return *this; }; //@} From 608e15562b9f3716cb238741562ac623bc75a529 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Mon, 29 Mar 2021 10:08:41 +0200 Subject: [PATCH 103/140] =?UTF-8?q?improved=20=CF=80=20precision?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vcg/math/base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/math/base.h b/vcg/math/base.h index a2ca912a..e721194c 100644 --- a/vcg/math/base.h +++ b/vcg/math/base.h @@ -165,7 +165,7 @@ namespace math { /* Some files do not define M_PI... */ #ifndef M_PI -#define M_PI 3.14159265358979323846 +#define M_PI 3.14159265358979323846264338327950288 #endif #ifndef SQRT_TWO From 7973ee6b48a7e59a7de6334d87cdcbfb98d71273 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Mon, 29 Mar 2021 11:55:47 +0200 Subject: [PATCH 104/140] fixed weird constness --- vcg/simplex/face/pos.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vcg/simplex/face/pos.h b/vcg/simplex/face/pos.h index 436226d1..b745e95f 100644 --- a/vcg/simplex/face/pos.h +++ b/vcg/simplex/face/pos.h @@ -68,19 +68,19 @@ public: /// Index of the edge int z; /// Pointer to the vertex - VertexType *v; + VertexType * v; /// Default constructor Pos() : f(0), z(-1), v(0) {} /// Constructor which associates the half-edge element with a face, its edge and its vertex /// \note that the input must be consistent, e.g. it should hold that \c vp==fp->V0(zp) or \c vp==fp->V1(zp) - Pos(FaceType * const fp, int const zp, VertexType * const vp) + Pos(FaceType * fp, int zp, VertexType * vp) { f=fp; z=zp; v=vp; assert((vp==fp->V0(zp))||(vp==fp->V1(zp))); } - Pos(FaceType * const fp, int const zp){f=fp; z=zp; v=f->V(zp);} - Pos(FaceType * const fp, VertexType * const vp) + Pos(FaceType * fp, int zp){f=fp; z=zp; v=f->V(zp);} + Pos(FaceType * fp, VertexType * vp) { f = fp; v = vp; From 895f8b0d03c6b964b33734ac20952353f6c78232 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Mon, 29 Mar 2021 17:29:44 +0200 Subject: [PATCH 105/140] fixed bug in const copy of mesh attributes --- vcg/complex/append.h | 120 ++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 54 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 6be6826e..63c44684 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -669,64 +669,76 @@ static void MeshAppendConst( // 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< PointerToAttribute >::iterator al, ar; + unsigned int id_r; + typename std::set< PointerToAttribute >::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 (auto v: mr.vert){ - if( !v.IsD() && (!selected || v.IsS())) - (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (const auto & v : mr.vert) + { + if( !v.IsD() && (!selected || v.IsS())) + (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto e: mr.edge){ - if( !e.IsD() && (!selected || e.IsS())) - (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (const auto & e : mr.edge) + { + if( !e.IsD() && (!selected || e.IsS())) + (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto f: mr.face) { - if( !f.IsD() && (!selected || f.IsS())) - (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (const auto & f : mr.face) + { + if( !f.IsD() && (!selected || f.IsS())) + (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); + ++id_r; + } + } + } - // 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 (auto t: mr.tetra) { - if( !t.IsD() && (!selected || t.IsS())) - (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); - ++id_r; - } - } - } + // 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 (const auto & t: mr.tetra) + { + if( !t.IsD() && (!selected || t.IsS())) + (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); + ++id_r; + } + } + } // per mesh attributes // if both ml and mr have an attribute with the same name, no action is done From 4c719ae5d0f176db45880a360cd70dcc9d443d3c Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 31 Mar 2021 11:10:14 +0200 Subject: [PATCH 106/140] Color4 ToUnsignedA8R8G8B8 function --- vcg/space/color4.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vcg/space/color4.h b/vcg/space/color4.h index d97e7480..8d7c71c3 100644 --- a/vcg/space/color4.h +++ b/vcg/space/color4.h @@ -261,6 +261,7 @@ inline static Color4 ColorRamp(const float &minf,const float &maxf ,float v ) inline static unsigned short ToUnsignedB5G5R5(const Color4 &) { return 0;} inline static unsigned short ToUnsignedR5G5B5(const Color4 &) { return 0;} +inline static unsigned int ToUnsignedA8R8G8B8(const Color4 &) { return 0;} inline static Color4 FromUnsignedB5G5R5(unsigned short) { @@ -439,6 +440,17 @@ inline unsigned short Color4::ToUnsignedR5G5B5(const Color4 +inline unsigned int Color4::ToUnsignedA8R8G8B8(const Color4 &cc) +{ + unsigned int r = cc[0]; + unsigned int g = cc[1]; + unsigned int b = cc[2]; + unsigned int a = cc[3]; + unsigned int res = (r << 16) | (g << 8) | (b) | (a << 24); + return res; +} + template<> inline Color4 Color4::FromUnsignedR5G5B5(unsigned short val) From 23082f1994e77ad8dd8401b09a8a0d1493ce6ef6 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 1 Apr 2021 10:11:26 +0200 Subject: [PATCH 107/140] remove unsupported polygonal flag from export ply --- wrap/io_trimesh/export_ply.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index d2c9d3cf..3874c5fc 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -844,7 +844,7 @@ namespace vcg { capability |= vcg::tri::io::Mask::IOM_WEDGTEXMULTI ; capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL ; capability |= vcg::tri::io::Mask::IOM_CAMERA ; - capability |= vcg::tri::io::Mask::IOM_BITPOLYGONAL; + //capability |= vcg::tri::io::Mask::IOM_BITPOLYGONAL; return capability; } From d4718bde6a1a9b0ceae22efaf825d87ea9216f43 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 1 Apr 2021 12:49:48 +0200 Subject: [PATCH 108/140] possibility to export double attributes in ply --- wrap/io_trimesh/export_ply.h | 4 +- wrap/io_trimesh/io_ply.h | 76 +++++++++++++++++++++++++----------- wrap/ply/plylib.h | 42 +++++++++----------- 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index 3874c5fc..ca097e96 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -211,7 +211,7 @@ namespace vcg { ); } for(size_t i=0;i0 && (pi.mask & Mask::IOM_EDGEINDEX) ) fprintf(fpout, diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index f52547e8..d939d610 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -41,6 +41,8 @@ Initial commit #define __VCGLIB_IOTRIMESH_IO_PLY +#include + /** @name Load and Save in Ply format */ @@ -64,37 +66,65 @@ This class can be passed to the ImporterPLY::Open() function for class PlyInfo { public: - typedef ::vcg::ply::PropDescriptor PropDescriptor ; + typedef ::vcg::ply::PropDescriptor PropDescriptor ; - void AddPerElemFloatAttribute(int elemType, const char *attrName, const char * propName=0) - { - static const char *elemStr[2]={"vertex","face"}; - std::vector *elemDescVec[2]={&(this->VertDescriptorVec), &(this->FaceDescriptorVec)}; - std::vector *elemNameVec[2]={&(this->VertAttrNameVec), &(this->FaceAttrNameVec)}; + void addPerElemScalarAttribute(int elemType, vcg::ply::PlyTypes propertyType, const std::string& attrName, std::string propName="") + { + if(propName=="") + propName=attrName; - if(propName==0) propName=attrName; - elemDescVec[elemType]->push_back(PropDescriptor()); - elemNameVec[elemType]->push_back(attrName); - elemDescVec[elemType]->back().elemname=elemStr[elemType]; - elemDescVec[elemType]->back().propname=strdup(propName); - elemDescVec[elemType]->back().stotype1 = vcg::ply::T_FLOAT; - elemDescVec[elemType]->back().memtype1 = vcg::ply::T_FLOAT; - } + if (elemType == 0){ //vertex + VertDescriptorVec.push_back(PropDescriptor()); + VertAttrNameVec.push_back(attrName); + VertDescriptorVec.back().elemname="vertex"; + VertDescriptorVec.back().propname=propName; + VertDescriptorVec.back().stotype1 = propertyType; + VertDescriptorVec.back().memtype1 = propertyType; + } + else if (elemType == 1){ //face + FaceDescriptorVec.push_back(PropDescriptor()); + FaceAttrNameVec.push_back(attrName); + FaceDescriptorVec.back().elemname="face"; + FaceDescriptorVec.back().propname=propName; + FaceDescriptorVec.back().stotype1 = propertyType; + FaceDescriptorVec.back().memtype1 = propertyType; + } + } - void AddPerVertexFloatAttribute(const char *attrName, const char *propName=0) { - AddPerElemFloatAttribute(0,attrName,propName); - } - void AddPerFaceFloatAttribute(const char *attrName, const char *propName=0) { - AddPerElemFloatAttribute(1,attrName,propName); - } + void AddPerElemFloatAttribute(int elemType, const std::string& attrName, std::string propName="") + { + addPerElemScalarAttribute(elemType, vcg::ply::T_FLOAT, attrName, propName); + } + + void AddPerElemDoubleAttribute(int elemType, const std::string& attrName, std::string propName="") + { + addPerElemScalarAttribute(elemType, vcg::ply::T_DOUBLE, attrName, propName); + } + + void addPerVertexScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") { + addPerElemScalarAttribute(0,attrType, attrName,propName); + } + + void AddPerVertexFloatAttribute(const std::string& attrName, std::string propName="") { + AddPerElemFloatAttribute(0,attrName,propName); + } + + void addPerFaceScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") { + addPerElemScalarAttribute(1,attrType, attrName,propName); + } + + void AddPerFaceFloatAttribute(const std::string& attrName, std::string propName="") { + AddPerElemFloatAttribute(1,attrName,propName); + } /* Note that saving a per vertex point3 attribute is a mess. * Actually require to allocate 3 float attribute and save them. And they are never deallocated... */ template - void AddPerVertexPoint3fAttribute(MeshType &m, const char *attrName, const char *propName="") + void AddPerVertexPoint3fAttribute(MeshType &m, const std::string& attrName, std::string propName="") { - if(propName==0) propName=attrName; + if(propName=="") + propName=attrName; const char *attrxyz[3] = { strdup((std::string(attrName)+std::string("_x")).c_str()), @@ -151,7 +181,7 @@ public: enum Error { - // Funzioni superiori + // Funzioni superiori E_NO_VERTEX = ply::E_MAXPLYERRORS+1, // 15 E_NO_FACE = ply::E_MAXPLYERRORS+2, // 16 E_SHORTFILE = ply::E_MAXPLYERRORS+3, // 17 diff --git a/wrap/ply/plylib.h b/wrap/ply/plylib.h index 59e5eddd..88470b20 100644 --- a/wrap/ply/plylib.h +++ b/wrap/ply/plylib.h @@ -112,33 +112,27 @@ typedef FILE * GZFILE; #endif - // Messaggio di errore -//extern const char * ply_error_msg[]; - - // TIPO FILE - - -// Descrittore esterno di propieta' +// Ply Property descriptor class PropDescriptor { public: - const char * elemname; // Nome dell'elemento - const char * propname; // Nome della propieta' - int stotype1; // Tipo dell'elemento su file (se lista tipo degli elementi della lista) - int memtype1; // Tipo dell'elemento in memoria (se lista tipo degli elementi della lista) - size_t offset1; // Offset del valore in memoria - int islist; // 1 se lista, 0 altrimenti - int alloclist; // 1 se alloca lista, 0 se preallocata - int stotype2; // Tipo del numero di elementi della lista su file - int memtype2; // Tipo del numero di elementi della lista in memoria - size_t offset2; // Offset valore memoria + std::string elemname; // name of the element (e.g. vertex) + std::string propname; // name of the property (e.g. x, y, red...) + int stotype1; // Type of the property in the file + int memtype1; // Type of the property in memory + size_t offset1; // Offset in memory + bool islist; // true if the property is a list + bool alloclist; // 1 se alloca lista, 0 se preallocata + int stotype2; // Type of the number of elements of the list in the file + int memtype2; // Type of the number of elements of the list in memory + size_t offset2; // Offset valore memoria - int format; // duplicazione del formato + int format; // duplicazione del formato - size_t stotypesize() const; // per sapere quanto e'grande un dato descrittore sul file - size_t memtypesize() const; // per sapere quanto e'grande un dato descrittore in memoria - const char *memtypename() const; - const char *stotypename() const; + size_t stotypesize() const; // per sapere quanto e'grande un dato descrittore sul file + size_t memtypesize() const; // per sapere quanto e'grande un dato descrittore in memoria + const char* memtypename() const; + const char* stotypename() const; }; // Reading Callback (used to copy a data prop) @@ -231,7 +225,7 @@ public: std::string name; // Nome dell'elemento int number; // Numero di elementi di questo tipo - std::vector props; // Vettore dinamico delle property + std::vector props; // Vettore dinamico delle property }; @@ -273,7 +267,7 @@ public: // Come sopra ma con descrittore inline int AddToRead( const PropDescriptor & p ) { - return AddToRead(p.elemname,p.propname,p.stotype1, + return AddToRead(p.elemname.c_str(),p.propname.c_str(),p.stotype1, p.memtype1,p.offset1,p.islist,p.alloclist,p.stotype2, p.memtype2,p.offset2 ); From 3fd845e5b7de358b5430f7e2baa8d4f56944b930 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 1 Apr 2021 18:54:15 +0200 Subject: [PATCH 109/140] const correctness for polygonal mesh --- vcg/simplex/face/component_polygon.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index 0a7cdd04..1fda9d1b 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -71,9 +71,9 @@ public: */ // ~PFVAdj(){ __Dealloc(); } - inline typename T::VertexType * & V( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]; } - inline typename T::VertexType * V( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } - inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } + inline typename T::VertexType * & V( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]; } + inline const typename T::VertexType * V( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } + inline const typename T::VertexType * cV( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @@ -90,11 +90,15 @@ public: inline const VertexType * cV2( const int j ) const { return cV((j+2)%this->VN());} inline CoordType &P( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]->P(); } + inline CoordType P( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]->cP(); } inline CoordType cP( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]->cP(); } inline CoordType & P0( const int j ) { return V(j)->P();} inline CoordType & P1( const int j ) { return V((j+1)%this->VN())->P();} inline CoordType & P2( const int j ) { return V((j+2)%this->VN())->P();} + inline CoordType P0( const int j ) const { return cV(j)->P();} + inline CoordType P1( const int j ) const { return cV((j+1)%this->VN())->P();} + inline CoordType P2( const int j ) const { return cV((j+2)%this->VN())->P();} inline CoordType cP0( const int j ) const { return cV(j)->P();} inline CoordType cP1( const int j ) const { return cV((j+1)%this->VN())->P();} inline CoordType cP2( const int j ) const { return cV((j+2)%this->VN())->P();} From 4001b5aa3403d8529f60c14368feddc201004ca6 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 2 Apr 2021 10:16:02 +0200 Subject: [PATCH 110/140] small refactor --- wrap/io_trimesh/io_ply.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index d939d610..39144305 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -73,21 +73,20 @@ public: if(propName=="") propName=attrName; + PropDescriptor p; + p.propname=propName; + p.stotype1 = propertyType; + p.memtype1 = propertyType; + if (elemType == 0){ //vertex - VertDescriptorVec.push_back(PropDescriptor()); VertAttrNameVec.push_back(attrName); - VertDescriptorVec.back().elemname="vertex"; - VertDescriptorVec.back().propname=propName; - VertDescriptorVec.back().stotype1 = propertyType; - VertDescriptorVec.back().memtype1 = propertyType; + p.elemname="vertex"; + VertDescriptorVec.push_back(p); } else if (elemType == 1){ //face - FaceDescriptorVec.push_back(PropDescriptor()); FaceAttrNameVec.push_back(attrName); - FaceDescriptorVec.back().elemname="face"; - FaceDescriptorVec.back().propname=propName; - FaceDescriptorVec.back().stotype1 = propertyType; - FaceDescriptorVec.back().memtype1 = propertyType; + p.elemname="face"; + FaceDescriptorVec.push_back(p); } } @@ -117,7 +116,6 @@ public: AddPerElemFloatAttribute(1,attrName,propName); } - /* Note that saving a per vertex point3 attribute is a mess. * Actually require to allocate 3 float attribute and save them. And they are never deallocated... */ template From 6509139fc67909ca20fb23942b944cec31b10cf0 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 2 Apr 2021 12:09:52 +0200 Subject: [PATCH 111/140] export point3f/d vertex attribute works ply files --- wrap/io_trimesh/export_ply.h | 1592 +++++++++++++++++----------------- wrap/io_trimesh/io_ply.h | 52 +- wrap/ply/plylib.cpp | 4 + wrap/ply/plylib.h | 4 + 4 files changed, 875 insertions(+), 777 deletions(-) diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index ca097e96..b5be20ca 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -34,827 +34,873 @@ #include #include #include - +#include #include namespace vcg { - namespace tri { - namespace io { +namespace tri { +namespace io { - template - class ExporterPLY - { - // Si occupa di convertire da un tipo all'altro. - // usata nella saveply per matchare i tipi tra stotype e memtype. - // Ad es se in memoria c'e' un int e voglio salvare un float - // src sara in effetti un puntatore a int il cui valore deve - // essere convertito al tipo di ritorno desiderato (stotype) +template +class ExporterPLY +{ + // Si occupa di convertire da un tipo all'altro. + // usata nella saveply per matchare i tipi tra stotype e memtype. + // Ad es se in memoria c'e' un int e voglio salvare un float + // src sara in effetti un puntatore a int il cui valore deve + // essere convertito al tipo di ritorno desiderato (stotype) - template - static void PlyConv(int mem_type, void *src, StoType &dest) - { - switch (mem_type){ - case ply::T_FLOAT : dest = (StoType) (* ((float *) src)); break; - case ply::T_DOUBLE: dest = (StoType) (* ((double *) src)); break; - case ply::T_INT : dest = (StoType) (* ((int *) src)); break; - case ply::T_SHORT : dest = (StoType) (* ((short *) src)); break; - case ply::T_CHAR : dest = (StoType) (* ((char *) src)); break; - case ply::T_UCHAR : dest = (StoType) (* ((unsigned char *)src)); break; - default : assert(0); - } - } + template + static void PlyConv(int mem_type, void *src, StoType &dest) + { + switch (mem_type){ + case ply::T_FLOAT : dest = (StoType) (* ((float *) src)); break; + case ply::T_DOUBLE: dest = (StoType) (* ((double *) src)); break; + case ply::T_INT : dest = (StoType) (* ((int *) src)); break; + case ply::T_SHORT : dest = (StoType) (* ((short *) src)); break; + case ply::T_CHAR : dest = (StoType) (* ((char *) src)); break; + case ply::T_UCHAR : dest = (StoType) (* ((unsigned char *)src)); break; + default : assert(0); + } + } - public: - typedef ::vcg::ply::PropDescriptor PropDescriptor ; - typedef typename SaveMeshType::ConstVertexPointer VertexPointer; - typedef typename SaveMeshType::ScalarType ScalarType; - typedef typename SaveMeshType::VertexType VertexType; - typedef typename SaveMeshType::FaceType FaceType; - typedef typename SaveMeshType::ConstFacePointer FacePointer; - typedef typename SaveMeshType::ConstVertexIterator VertexIterator; - typedef typename SaveMeshType::ConstFaceIterator FaceIterator; - typedef typename SaveMeshType::ConstEdgeIterator EdgeIterator; - typedef typename vcg::Shot::ScalarType ShotScalarType; +public: + typedef ::vcg::ply::PropDescriptor PropDescriptor ; + typedef typename SaveMeshType::ConstVertexPointer VertexPointer; + typedef typename SaveMeshType::ScalarType ScalarType; + typedef typename SaveMeshType::VertexType VertexType; + typedef typename SaveMeshType::FaceType FaceType; + typedef typename SaveMeshType::ConstFacePointer FacePointer; + typedef typename SaveMeshType::ConstVertexIterator VertexIterator; + typedef typename SaveMeshType::ConstFaceIterator FaceIterator; + typedef typename SaveMeshType::ConstEdgeIterator EdgeIterator; + typedef typename vcg::Shot::ScalarType ShotScalarType; - static int Save(const SaveMeshType &m, const char * filename, bool binary=true) - { - PlyInfo pi; - return Save(m,filename,binary,pi); - } + static int Save(const SaveMeshType &m, const char * filename, bool binary=true) + { + PlyInfo pi; + return Save(m,filename,binary,pi); + } - static int Save(const SaveMeshType &m, const char * filename, int savemask, bool binary = true, CallBackPos *cb=0 ) - { - PlyInfo pi; - pi.mask=savemask; - return Save(m,filename,binary,pi,cb); - } + static int Save(const SaveMeshType &m, const char * filename, int savemask, bool binary = true, CallBackPos *cb=0 ) + { + PlyInfo pi; + pi.mask=savemask; + return Save(m,filename,binary,pi,cb); + } - static int Save(const SaveMeshType &m, const char * filename, bool binary, const PlyInfo &pi, CallBackPos *cb=0) // V1.0 - { - FILE * fpout; - const char * hbin = "binary_little_endian"; - const char * hasc = "ascii"; - const char * h; - //Coord ScalarType - const int DGT = vcg::tri::io::Precision::digits(); - const int DGTS = vcg::tri::io::Precision::digits(); - const int DGTVQ = vcg::tri::io::Precision::digits(); - const int DGTVR = vcg::tri::io::Precision::digits(); - const int DGTFQ = vcg::tri::io::Precision::digits(); - bool saveTexIndexFlag = false; + static int Save(const SaveMeshType &m, const char * filename, bool binary, const PlyInfo &pi, CallBackPos *cb=0) // V1.0 + { + FILE * fpout; + const char * hbin = "binary_little_endian"; + const char * hasc = "ascii"; + const char * h; + //Coord ScalarType + const int DGT = vcg::tri::io::Precision::digits(); + const int DGTS = vcg::tri::io::Precision::digits(); + const int DGTVQ = vcg::tri::io::Precision::digits(); + const int DGTVR = vcg::tri::io::Precision::digits(); + const int DGTFQ = vcg::tri::io::Precision::digits(); + bool saveTexIndexFlag = false; - if(binary) h=hbin; - else h=hasc; + if(binary) h=hbin; + else h=hasc; - fpout = fopen(filename,"wb"); - if(fpout==NULL) { - //pi.status=::vcg::ply::E_CANTOPEN; - return ::vcg::ply::E_CANTOPEN; - } - fprintf(fpout, - "ply\n" - "format %s 1.0\n" - "comment VCGLIB generated\n" - ,h - ); + fpout = fopen(filename,"wb"); + if(fpout==NULL) { + //pi.status=::vcg::ply::E_CANTOPEN; + return ::vcg::ply::E_CANTOPEN; + } + fprintf(fpout, + "ply\n" + "format %s 1.0\n" + "comment VCGLIB generated\n" , + h); - if (((pi.mask & Mask::IOM_WEDGTEXCOORD) != 0) || ((pi.mask & Mask::IOM_VERTTEXCOORD) != 0)) - { - const char * TFILE = "TextureFile"; + if (((pi.mask & Mask::IOM_WEDGTEXCOORD) != 0) || ((pi.mask & Mask::IOM_VERTTEXCOORD) != 0)) + { + const char * TFILE = "TextureFile"; - for(size_t i=0; i < m.textures.size(); ++i) - fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(m.textures[i].c_str()) ); + for(size_t i=0; i < m.textures.size(); ++i) + fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(m.textures[i].c_str()) ); - if(m.textures.size()>1 && (HasPerWedgeTexCoord(m) || HasPerVertexTexCoord(m))) saveTexIndexFlag = true; - } + if(m.textures.size()>1 && (HasPerWedgeTexCoord(m) || HasPerVertexTexCoord(m))) saveTexIndexFlag = true; + } - if((pi.mask & Mask::IOM_CAMERA)) - { - const char* cmtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"element camera 1\n"); - fprintf(fpout,"property %s view_px\n",cmtp); - fprintf(fpout,"property %s view_py\n",cmtp); - fprintf(fpout,"property %s view_pz\n",cmtp); - fprintf(fpout,"property %s x_axisx\n",cmtp); - fprintf(fpout,"property %s x_axisy\n",cmtp); - fprintf(fpout,"property %s x_axisz\n",cmtp); - fprintf(fpout,"property %s y_axisx\n",cmtp); - fprintf(fpout,"property %s y_axisy\n",cmtp); - fprintf(fpout,"property %s y_axisz\n",cmtp); - fprintf(fpout,"property %s z_axisx\n",cmtp); - fprintf(fpout,"property %s z_axisy\n",cmtp); - fprintf(fpout,"property %s z_axisz\n",cmtp); - fprintf(fpout,"property %s focal\n",cmtp); - fprintf(fpout,"property %s scalex\n",cmtp); - fprintf(fpout,"property %s scaley\n",cmtp); - fprintf(fpout,"property %s centerx\n",cmtp); - fprintf(fpout,"property %s centery\n",cmtp); - fprintf(fpout,"property int viewportx\n"); - fprintf(fpout,"property int viewporty\n"); - fprintf(fpout,"property %s k1\n",cmtp); - fprintf(fpout,"property %s k2\n",cmtp); - fprintf(fpout,"property %s k3\n",cmtp); - fprintf(fpout,"property %s k4\n",cmtp); - } + if((pi.mask & Mask::IOM_CAMERA)) + { + const char* cmtp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"element camera 1\n"); + fprintf(fpout,"property %s view_px\n",cmtp); + fprintf(fpout,"property %s view_py\n",cmtp); + fprintf(fpout,"property %s view_pz\n",cmtp); + fprintf(fpout,"property %s x_axisx\n",cmtp); + fprintf(fpout,"property %s x_axisy\n",cmtp); + fprintf(fpout,"property %s x_axisz\n",cmtp); + fprintf(fpout,"property %s y_axisx\n",cmtp); + fprintf(fpout,"property %s y_axisy\n",cmtp); + fprintf(fpout,"property %s y_axisz\n",cmtp); + fprintf(fpout,"property %s z_axisx\n",cmtp); + fprintf(fpout,"property %s z_axisy\n",cmtp); + fprintf(fpout,"property %s z_axisz\n",cmtp); + fprintf(fpout,"property %s focal\n",cmtp); + fprintf(fpout,"property %s scalex\n",cmtp); + fprintf(fpout,"property %s scaley\n",cmtp); + fprintf(fpout,"property %s centerx\n",cmtp); + fprintf(fpout,"property %s centery\n",cmtp); + fprintf(fpout,"property int viewportx\n"); + fprintf(fpout,"property int viewporty\n"); + fprintf(fpout,"property %s k1\n",cmtp); + fprintf(fpout,"property %s k2\n",cmtp); + fprintf(fpout,"property %s k3\n",cmtp); + fprintf(fpout,"property %s k4\n",cmtp); + } - const char* vttp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"element vertex %d\n",m.vn); - fprintf(fpout,"property %s x\n",vttp); - fprintf(fpout,"property %s y\n",vttp); - fprintf(fpout,"property %s z\n",vttp); + const char* vttp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"element vertex %d\n",m.vn); + fprintf(fpout,"property %s x\n",vttp); + fprintf(fpout,"property %s y\n",vttp); + fprintf(fpout,"property %s z\n",vttp); - if( HasPerVertexNormal(m) &&( pi.mask & Mask::IOM_VERTNORMAL) ) - { - fprintf(fpout,"property %s nx\n",vttp); - fprintf(fpout,"property %s ny\n",vttp); - fprintf(fpout,"property %s nz\n",vttp); - } + if( HasPerVertexNormal(m) &&( pi.mask & Mask::IOM_VERTNORMAL) ) + { + fprintf(fpout,"property %s nx\n",vttp); + fprintf(fpout,"property %s ny\n",vttp); + fprintf(fpout,"property %s nz\n",vttp); + } - if( HasPerVertexFlags(m) &&( pi.mask & Mask::IOM_VERTFLAGS) ) - { - fprintf(fpout, - "property int flags\n" - ); - } + if( HasPerVertexFlags(m) &&( pi.mask & Mask::IOM_VERTFLAGS) ) + { + fprintf(fpout, + "property int flags\n"); + } - if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) - { - fprintf(fpout, - "property uchar red\n" - "property uchar green\n" - "property uchar blue\n" - "property uchar alpha\n" - ); - } + if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) + { + fprintf(fpout, + "property uchar red\n" + "property uchar green\n" + "property uchar blue\n" + "property uchar alpha\n"); + } - if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) - { - const char* vqtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"property %s quality\n",vqtp); - } + if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) + { + const char* vqtp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"property %s quality\n",vqtp); + } - if( tri::HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ) - { - const char* rdtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"property %s radius\n",rdtp); - } - if( ( HasPerVertexTexCoord(m) && pi.mask & Mask::IOM_VERTTEXCOORD ) ) - { - fprintf(fpout, - "property float texture_u\n" - "property float texture_v\n" - ); - } - for(size_t i=0;i::typeName(); + fprintf(fpout,"property %s radius\n",rdtp); + } + if( ( HasPerVertexTexCoord(m) && pi.mask & Mask::IOM_VERTTEXCOORD ) ) + { + fprintf(fpout, + "property float texture_u\n" + "property float texture_v\n"); + } + for(size_t i=0;i::typeName(); + fprintf(fpout, "property %s nx\n", fntp); + fprintf(fpout, "property %s ny\n", fntp); + fprintf(fpout, "property %s nz\n", fntp); + } + + if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) + { + const char* fqtp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"property %s quality\n",fqtp); + } + + for(size_t i=0;i0 && (pi.mask & Mask::IOM_EDGEINDEX) ) + fprintf( + fpout, + "element edge %d\n" "property int vertex1\n""property int vertex2\n",m.en); + fprintf(fpout, "end_header\n" ); + + // Salvataggio camera + if((pi.mask & Mask::IOM_CAMERA)) + { + if(binary) + { + ShotScalarType t[17]; + + t[ 0] = (ShotScalarType)m.shot.Extrinsics.Tra()[0]; + t[ 1] = (ShotScalarType)m.shot.Extrinsics.Tra()[1]; + t[ 2] = (ShotScalarType)m.shot.Extrinsics.Tra()[2]; + t[ 3] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][0]; + t[ 4] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][1]; + t[ 5] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][2]; + t[ 6] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][0]; + t[ 7] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][1]; + t[ 8] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][2]; + t[ 9] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][0]; + t[10] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][1]; + t[11] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][2]; + t[12] = (ShotScalarType)m.shot.Intrinsics.FocalMm; + t[13] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[0]; + t[14] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[1]; + t[15] = (ShotScalarType)m.shot.Intrinsics.CenterPx[0]; + t[16] = (ShotScalarType)m.shot.Intrinsics.CenterPx[1]; + fwrite(t,sizeof(ShotScalarType),17,fpout); + + fwrite( &m.shot.Intrinsics.ViewportPx[0],sizeof(int),2,fpout ); + + t[ 0] = (ShotScalarType)m.shot.Intrinsics.k[0]; + t[ 1] = (ShotScalarType)m.shot.Intrinsics.k[1]; + t[ 2] = (ShotScalarType)m.shot.Intrinsics.k[2]; + t[ 3] = (ShotScalarType)m.shot.Intrinsics.k[3]; + fwrite(t,sizeof(ShotScalarType),4,fpout); + } + else + { + fprintf(fpout,"%.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %d %d %.*g %.*g %.*g %.*g\n" + ,DGTS,-m.shot.Extrinsics.Tra()[0] + ,DGTS,-m.shot.Extrinsics.Tra()[1] + ,DGTS,-m.shot.Extrinsics.Tra()[2] + ,DGTS,m.shot.Extrinsics.Rot()[0][0] + ,DGTS,m.shot.Extrinsics.Rot()[0][1] + ,DGTS,m.shot.Extrinsics.Rot()[0][2] + ,DGTS,m.shot.Extrinsics.Rot()[1][0] + ,DGTS,m.shot.Extrinsics.Rot()[1][1] + ,DGTS,m.shot.Extrinsics.Rot()[1][2] + ,DGTS,m.shot.Extrinsics.Rot()[2][0] + ,DGTS,m.shot.Extrinsics.Rot()[2][1] + ,DGTS,m.shot.Extrinsics.Rot()[2][2] + ,DGTS,m.shot.Intrinsics.FocalMm + ,DGTS,m.shot.Intrinsics.PixelSizeMm[0] + ,DGTS,m.shot.Intrinsics.PixelSizeMm[1] + ,DGTS,m.shot.Intrinsics.CenterPx[0] + ,DGTS,m.shot.Intrinsics.CenterPx[1] + ,m.shot.Intrinsics.ViewportPx[0] + ,m.shot.Intrinsics.ViewportPx[1] + ,DGTS,m.shot.Intrinsics.k[0] + ,DGTS,m.shot.Intrinsics.k[1] + ,DGTS,m.shot.Intrinsics.k[2] + ,DGTS,m.shot.Intrinsics.k[3] + ); + } + } + + + int j; + std::vector FlagV; + VertexPointer vp; + VertexIterator vi; + SimpleTempData indices(m.vert); + + std::vector > thfv(pi.VertDescriptorVec.size()); + std::vector > thdv(pi.VertDescriptorVec.size()); + std::vector > thiv(pi.VertDescriptorVec.size()); + std::vector > thsv(pi.VertDescriptorVec.size()); + std::vector > thcv(pi.VertDescriptorVec.size()); + std::vector > thuv(pi.VertDescriptorVec.size()); + std::vector > thp3fv(pi.VertDescriptorVec.size()); + std::vector > thp3dv(pi.VertDescriptorVec.size()); + + for(size_t i=0;i::typeName(); - fprintf(fpout, "property %s nx\n", fntp); - fprintf(fpout, "property %s ny\n", fntp); - fprintf(fpout, "property %s nz\n", fntp); + case ply::T_FLOAT : thfv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + default : assert(0); + } + } + else { + switch (pi.VertDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : thp3fv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_DOUBLE : thp3dv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + default : assert(0); + } + } + } + } + std::vector > thff(pi.FaceDescriptorVec.size()); + std::vector > thdf(pi.FaceDescriptorVec.size()); + std::vector > thif(pi.FaceDescriptorVec.size()); + std::vector > thsf(pi.FaceDescriptorVec.size()); + std::vector > thcf(pi.FaceDescriptorVec.size()); + std::vector > thuf(pi.FaceDescriptorVec.size()); + + for(size_t i=0;i::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_SHORT : thsf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_CHAR : thcf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + default : assert(0); + } + } + } + + for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi){ + vp=&(*vi); + indices[vi] = j; + //((m.vn+m.fn) != 0) all vertices and faces have been marked as deleted but the are still in the vert/face vectors + if(cb && ((j%1000)==0) && ((m.vn+m.fn) != 0) )(*cb)( (100*j)/(m.vn+m.fn), "Saving Vertices"); + + if( !HasPerVertexFlags(m) || !vp->IsD() ) + { + if(binary) + { + ScalarType t; + + t = ScalarType(vp->P()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->P()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->P()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + + if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) + { + t = ScalarType(vp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + } + if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS) ) + fwrite(&(vp->Flags()),sizeof(int),1,fpout); + + if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ){ + auto c = vp->C(); + fwrite(&c,sizeof(char),4,fpout); } - if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) - { - const char* fqtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"property %s quality\n",fqtp); - } + if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ){ + auto q = vp->Q(); + fwrite(&q, sizeof(typename VertexType::QualityType),1,fpout); + } - for(size_t i=0;i0 && (pi.mask & Mask::IOM_EDGEINDEX) ) - fprintf(fpout, - "element edge %d\n" - "property int vertex1\n" - "property int vertex2\n" - ,m.en - ); - fprintf(fpout, "end_header\n" ); + if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ){ + auto r = vp->R(); + fwrite(&r,sizeof(typename VertexType::RadiusType),1,fpout); + } - // Salvataggio camera - if((pi.mask & Mask::IOM_CAMERA)) - { - if(binary) - { - ShotScalarType t[17]; + if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) + { + t = ScalarType(vp->T().u()); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->T().v()); fwrite(&t,sizeof(ScalarType),1,fpout); + } - t[ 0] = (ShotScalarType)m.shot.Extrinsics.Tra()[0]; - t[ 1] = (ShotScalarType)m.shot.Extrinsics.Tra()[1]; - t[ 2] = (ShotScalarType)m.shot.Extrinsics.Tra()[2]; - t[ 3] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][0]; - t[ 4] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][1]; - t[ 5] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][2]; - t[ 6] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][0]; - t[ 7] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][1]; - t[ 8] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][2]; - t[ 9] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][0]; - t[10] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][1]; - t[11] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][2]; - t[12] = (ShotScalarType)m.shot.Intrinsics.FocalMm; - t[13] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[0]; - t[14] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[1]; - t[15] = (ShotScalarType)m.shot.Intrinsics.CenterPx[0]; - t[16] = (ShotScalarType)m.shot.Intrinsics.CenterPx[1]; - fwrite(t,sizeof(ShotScalarType),17,fpout); - - fwrite( &m.shot.Intrinsics.ViewportPx[0],sizeof(int),2,fpout ); - - t[ 0] = (ShotScalarType)m.shot.Intrinsics.k[0]; - t[ 1] = (ShotScalarType)m.shot.Intrinsics.k[1]; - t[ 2] = (ShotScalarType)m.shot.Intrinsics.k[2]; - t[ 3] = (ShotScalarType)m.shot.Intrinsics.k[3]; - fwrite(t,sizeof(ShotScalarType),4,fpout); - } - else - { - fprintf(fpout,"%.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %d %d %.*g %.*g %.*g %.*g\n" - ,DGTS,-m.shot.Extrinsics.Tra()[0] - ,DGTS,-m.shot.Extrinsics.Tra()[1] - ,DGTS,-m.shot.Extrinsics.Tra()[2] - ,DGTS,m.shot.Extrinsics.Rot()[0][0] - ,DGTS,m.shot.Extrinsics.Rot()[0][1] - ,DGTS,m.shot.Extrinsics.Rot()[0][2] - ,DGTS,m.shot.Extrinsics.Rot()[1][0] - ,DGTS,m.shot.Extrinsics.Rot()[1][1] - ,DGTS,m.shot.Extrinsics.Rot()[1][2] - ,DGTS,m.shot.Extrinsics.Rot()[2][0] - ,DGTS,m.shot.Extrinsics.Rot()[2][1] - ,DGTS,m.shot.Extrinsics.Rot()[2][2] - ,DGTS,m.shot.Intrinsics.FocalMm - ,DGTS,m.shot.Intrinsics.PixelSizeMm[0] - ,DGTS,m.shot.Intrinsics.PixelSizeMm[1] - ,DGTS,m.shot.Intrinsics.CenterPx[0] - ,DGTS,m.shot.Intrinsics.CenterPx[1] - ,m.shot.Intrinsics.ViewportPx[0] - ,m.shot.Intrinsics.ViewportPx[1] - ,DGTS,m.shot.Intrinsics.k[0] - ,DGTS,m.shot.Intrinsics.k[1] - ,DGTS,m.shot.Intrinsics.k[2] - ,DGTS,m.shot.Intrinsics.k[3] - ); - } - } - - - int j; - std::vector FlagV; - VertexPointer vp; - VertexIterator vi; - SimpleTempData indices(m.vert); - - std::vector > thfv(pi.VertDescriptorVec.size()); - std::vector > thdv(pi.VertDescriptorVec.size()); - std::vector > thiv(pi.VertDescriptorVec.size()); - std::vector > thsv(pi.VertDescriptorVec.size()); - std::vector > thcv(pi.VertDescriptorVec.size()); - std::vector > thuv(pi.VertDescriptorVec.size()); - - for(size_t i=0;i::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - default : assert(0); - } - } - } - std::vector > thff(pi.FaceDescriptorVec.size()); - std::vector > thdf(pi.FaceDescriptorVec.size()); - std::vector > thif(pi.FaceDescriptorVec.size()); - std::vector > thsf(pi.FaceDescriptorVec.size()); - std::vector > thcf(pi.FaceDescriptorVec.size()); - std::vector > thuf(pi.FaceDescriptorVec.size()); - - for(size_t i=0;i::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_SHORT : thsf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_CHAR : thcf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - default : assert(0); - } - } - } - - - - - for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi){ - vp=&(*vi); - indices[vi] = j; - //((m.vn+m.fn) != 0) all vertices and faces have been marked as deleted but the are still in the vert/face vectors - if(cb && ((j%1000)==0) && ((m.vn+m.fn) != 0) )(*cb)( (100*j)/(m.vn+m.fn), "Saving Vertices"); - - if( !HasPerVertexFlags(m) || !vp->IsD() ) - { - if(binary) - { - ScalarType t; - - t = ScalarType(vp->P()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->P()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->P()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); - - if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) - { - t = ScalarType(vp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); - } - if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS) ) - fwrite(&(vp->Flags()),sizeof(int),1,fpout); - - if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ){ - auto c = vp->C(); - fwrite(&c,sizeof(char),4,fpout); - } - - if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ){ - auto q = vp->Q(); - fwrite(&q, sizeof(typename VertexType::QualityType),1,fpout); - } - - if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ){ - auto r = vp->R(); - fwrite(&r,sizeof(typename VertexType::RadiusType),1,fpout); - } - - if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) - { - t = ScalarType(vp->T().u()); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->T().v()); fwrite(&t,sizeof(ScalarType),1,fpout); - } - - for(size_t i=0;iP()[0],DGT,vp->P()[1],DGT,vp->P()[2]); - - if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) - fprintf(fpout,"%.*g %.*g %.*g " ,DGT,ScalarType(vp->N()[0]),DGT,ScalarType(vp->N()[1]),DGT,ScalarType(vp->N()[2])); - - if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS)) - fprintf(fpout,"%d ",vp->Flags()); - - if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) - fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); - - if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) - fprintf(fpout,"%.*g ",DGTVQ,vp->Q()); - - if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ) - fprintf(fpout,"%.*g ",DGTVR,vp->R()); - - if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) - fprintf(fpout,"%f %f",vp->T().u(),vp->T().v()); - - for(size_t i=0;iIsD() ) - { fcnt++; - if(binary) - { - vv[0]=indices[fp->cV(0)]; - vv[1]=indices[fp->cV(1)]; - vv[2]=indices[fp->cV(2)]; - fwrite(&b3char,sizeof(char),1,fpout); - fwrite(vv,sizeof(int),3,fpout); - - if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) ){ - auto fl = fp->Flags(); - fwrite(&fl,sizeof(int),1,fpout); - } - - if( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // Note that you can save VT as WT if you really want it... - { - fwrite(&b6char,sizeof(char),1,fpout); - float t[6]; - for(int k=0;k<3;++k) - { - t[k*2+0] = fp->V(k)->T().u(); - t[k*2+1] = fp->V(k)->T().v(); - } - fwrite(t,sizeof(float),6,fpout); - } - else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) - { - fwrite(&b6char,sizeof(char),1,fpout); - float t[6]; - for(int k=0;k<3;++k) - { - t[k*2+0] = fp->WT(k).u(); - t[k*2+1] = fp->WT(k).v(); - } - fwrite(t,sizeof(float),6,fpout); - } - - if(saveTexIndexFlag) - { - int t = fp->WT(0).n(); - fwrite(&t,sizeof(int),1,fpout); - } - - if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) - fwrite(&( fp->C() ),sizeof(char),4,fpout); - - - if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) - { - fwrite(&b9char,sizeof(char),1,fpout); - float t[3]; - for(int z=0;z<3;++z) - { - t[0] = float(fp->WC(z)[0])/255; - t[1] = float(fp->WC(z)[1])/255; - t[2] = float(fp->WC(z)[2])/255; - fwrite( t,sizeof(float),3,fpout); - } - } - - if( HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL) ) - { - ScalarType t; - t = ScalarType(fp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(fp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(fp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + for(size_t i=0;iP()[0],DGT,vp->P()[1],DGT,vp->P()[2]); - if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) - fwrite( &(fp->Q()),sizeof(typename FaceType::ScalarType),1,fpout); + if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) + fprintf(fpout,"%.*g %.*g %.*g " ,DGT,ScalarType(vp->N()[0]),DGT,ScalarType(vp->N()[1]),DGT,ScalarType(vp->N()[2])); + + if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS)) + fprintf(fpout,"%d ",vp->Flags()); + + if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) + fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); + + if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) + fprintf(fpout,"%.*g ",DGTVQ,vp->Q()); + + if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ) + fprintf(fpout,"%.*g ",DGTVR,vp->R()); + + if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) + fprintf(fpout,"%f %f",vp->T().u(),vp->T().v()); + + for(size_t i=0;iIsD() ) + { fcnt++; + if(binary) + { + vv[0]=indices[fp->cV(0)]; + vv[1]=indices[fp->cV(1)]; + vv[2]=indices[fp->cV(2)]; + fwrite(&b3char,sizeof(char),1,fpout); + fwrite(vv,sizeof(int),3,fpout); + + if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) ){ + auto fl = fp->Flags(); + fwrite(&fl,sizeof(int),1,fpout); + } + + if( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // Note that you can save VT as WT if you really want it... + { + fwrite(&b6char,sizeof(char),1,fpout); + float t[6]; + for(int k=0;k<3;++k) + { + t[k*2+0] = fp->V(k)->T().u(); + t[k*2+1] = fp->V(k)->T().v(); + } + fwrite(t,sizeof(float),6,fpout); + } + else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) + { + fwrite(&b6char,sizeof(char),1,fpout); + float t[6]; + for(int k=0;k<3;++k) + { + t[k*2+0] = fp->WT(k).u(); + t[k*2+1] = fp->WT(k).v(); + } + fwrite(t,sizeof(float),6,fpout); + } + + if(saveTexIndexFlag) + { + int t = fp->WT(0).n(); + fwrite(&t,sizeof(int),1,fpout); + } + + if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) + fwrite(&( fp->C() ),sizeof(char),4,fpout); - for(size_t i=0;iVN()); - for(int k=0;kVN();++k) - fprintf(fpout,"%d ",indices[fp->cV(k)]); + if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) + { + fwrite(&b9char,sizeof(char),1,fpout); + float t[3]; + for(int z=0;z<3;++z) + { + t[0] = float(fp->WC(z)[0])/255; + t[1] = float(fp->WC(z)[1])/255; + t[2] = float(fp->WC(z)[2])/255; + fwrite( t,sizeof(float),3,fpout); + } + } - if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS )) - fprintf(fpout,"%d ",fp->Flags()); + if( HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL) ) + { + ScalarType t; + t = ScalarType(fp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(fp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(fp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + } - if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // you can save VT as WT if you really want it... - { - fprintf(fpout,"%d ",fp->VN()*2); - for(int k=0;kVN();++k) - fprintf(fpout,"%f %f " - ,fp->V(k)->T().u() - ,fp->V(k)->T().v() - ); - } - else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) - { - fprintf(fpout,"%d ",fp->VN()*2); - for(int k=0;kVN();++k) - fprintf(fpout,"%f %f " - ,fp->WT(k).u() - ,fp->WT(k).v() - ); - } - - if(saveTexIndexFlag) - { - fprintf(fpout,"%d ",fp->WT(0).n()); - } - - if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) - { - fprintf(fpout, "%u %u %u %u ", fp->C()[0], fp->C()[1], fp->C()[2], fp->C()[3]); - } - else if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) - { - fprintf(fpout,"9 "); - for(int z=0;z<3;++z) - fprintf(fpout,"%g %g %g " - ,double(fp->WC(z)[0])/255 - ,double(fp->WC(z)[1])/255 - ,double(fp->WC(z)[2])/255 - ); - } - - if (HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL)) - fprintf(fpout,"%.*g %.*g %.*g " ,DGT, ScalarType(fp->N()[0]),DGT,ScalarType(fp->N()[1]),DGT,ScalarType(fp->N()[2])); - - if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) - fprintf(fpout,"%.*g ",DGTFQ,fp->Q()); - - for(size_t i=0;iIsD() ) - { - ++ecnt; - if(binary) - { - eauxvv[0]=indices[ei->cV(0)]; - eauxvv[1]=indices[ei->cV(1)]; - fwrite(eauxvv,sizeof(int),2,fpout); - } - else // ***** ASCII ***** - fprintf(fpout,"%d %d \n", indices[ei->cV(0)], indices[ei->cV(1)]); - } - } - assert(ecnt==m.en); - } - int result = 0; - if (ferror(fpout)) result = ply::E_STREAMERROR; - fclose(fpout); - return result; - } - - static const char *ErrorMsg(int error) - { - static std::vector ply_error_msg; - if(ply_error_msg.empty()) - { - ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS ); - ply_error_msg[ply::E_NOERROR ]="No errors"; - ply_error_msg[ply::E_CANTOPEN ]="Can't open file"; - ply_error_msg[ply::E_NOTHEADER ]="Header not found"; - ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header"; - ply_error_msg[ply::E_NOFORMAT ]="Format not found"; - ply_error_msg[ply::E_SYNTAX ]="Syntax error on header"; - ply_error_msg[ply::E_PROPOUTOFELEMENT ]="Property without element"; - ply_error_msg[ply::E_BADTYPENAME ]="Bad type name"; - ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found"; - ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found"; - ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread"; - ply_error_msg[ply::E_INCOMPATIBLETYPE ]="Incompatible type"; - ply_error_msg[ply::E_BADCAST ]="Bad cast"; - - ply_error_msg[ply::E_STREAMERROR ] = "Output Stream Error"; - - ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found"; - ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found"; - ply_error_msg[PlyInfo::E_SHORTFILE ]="Unespected eof"; - ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices"; - ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face"; - ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates"; - ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices"; - } - - if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error"; - else return ply_error_msg[error].c_str(); - }; - - static int GetExportMaskCapability() - { - int capability = 0; - capability |= vcg::tri::io::Mask::IOM_VERTCOORD ; - capability |= vcg::tri::io::Mask::IOM_VERTFLAGS ; - capability |= vcg::tri::io::Mask::IOM_VERTCOLOR ; - capability |= vcg::tri::io::Mask::IOM_VERTQUALITY ; - capability |= vcg::tri::io::Mask::IOM_VERTNORMAL ; - capability |= vcg::tri::io::Mask::IOM_VERTRADIUS ; - capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD ; - capability |= vcg::tri::io::Mask::IOM_FACEINDEX ; - capability |= vcg::tri::io::Mask::IOM_FACEFLAGS ; - capability |= vcg::tri::io::Mask::IOM_FACECOLOR ; - capability |= vcg::tri::io::Mask::IOM_FACEQUALITY ; - // capability |= vcg::tri::io::Mask::IOM_FACENORMAL ; - capability |= vcg::tri::io::Mask::IOM_WEDGCOLOR ; - capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD ; - capability |= vcg::tri::io::Mask::IOM_WEDGTEXMULTI ; - capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL ; - capability |= vcg::tri::io::Mask::IOM_CAMERA ; - //capability |= vcg::tri::io::Mask::IOM_BITPOLYGONAL; - return capability; - } + if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) + fwrite( &(fp->Q()),sizeof(typename FaceType::ScalarType),1,fpout); - }; // end class + for(size_t i=0;iVN()); + for(int k=0;kVN();++k) + fprintf(fpout,"%d ",indices[fp->cV(k)]); + + if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS )) + fprintf(fpout,"%d ",fp->Flags()); + + if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // you can save VT as WT if you really want it... + { + fprintf(fpout,"%d ",fp->VN()*2); + for(int k=0;kVN();++k) + fprintf(fpout,"%f %f " + ,fp->V(k)->T().u() + ,fp->V(k)->T().v() + ); + } + else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) + { + fprintf(fpout,"%d ",fp->VN()*2); + for(int k=0;kVN();++k) + fprintf(fpout,"%f %f " + ,fp->WT(k).u() + ,fp->WT(k).v() + ); + } + + if(saveTexIndexFlag) + { + fprintf(fpout,"%d ",fp->WT(0).n()); + } + + if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) + { + fprintf(fpout, "%u %u %u %u ", fp->C()[0], fp->C()[1], fp->C()[2], fp->C()[3]); + } + else if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) + { + fprintf(fpout,"9 "); + for(int z=0;z<3;++z) + fprintf(fpout,"%g %g %g " + ,double(fp->WC(z)[0])/255 + ,double(fp->WC(z)[1])/255 + ,double(fp->WC(z)[2])/255 + ); + } + + if (HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL)) + fprintf(fpout,"%.*g %.*g %.*g " ,DGT, ScalarType(fp->N()[0]),DGT,ScalarType(fp->N()[1]),DGT,ScalarType(fp->N()[2])); + + if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) + fprintf(fpout,"%.*g ",DGTFQ,fp->Q()); + + for(size_t i=0;iIsD() ) + { + ++ecnt; + if(binary) + { + eauxvv[0]=indices[ei->cV(0)]; + eauxvv[1]=indices[ei->cV(1)]; + fwrite(eauxvv,sizeof(int),2,fpout); + } + else // ***** ASCII ***** + fprintf(fpout,"%d %d \n", indices[ei->cV(0)], indices[ei->cV(1)]); + } + } + assert(ecnt==m.en); + } + int result = 0; + if (ferror(fpout)) result = ply::E_STREAMERROR; + fclose(fpout); + return result; + } + + static const char *ErrorMsg(int error) + { + static std::vector ply_error_msg; + if(ply_error_msg.empty()) + { + ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS ); + ply_error_msg[ply::E_NOERROR ]="No errors"; + ply_error_msg[ply::E_CANTOPEN ]="Can't open file"; + ply_error_msg[ply::E_NOTHEADER ]="Header not found"; + ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header"; + ply_error_msg[ply::E_NOFORMAT ]="Format not found"; + ply_error_msg[ply::E_SYNTAX ]="Syntax error on header"; + ply_error_msg[ply::E_PROPOUTOFELEMENT ]="Property without element"; + ply_error_msg[ply::E_BADTYPENAME ]="Bad type name"; + ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found"; + ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found"; + ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread"; + ply_error_msg[ply::E_INCOMPATIBLETYPE ]="Incompatible type"; + ply_error_msg[ply::E_BADCAST ]="Bad cast"; + + ply_error_msg[ply::E_STREAMERROR ] = "Output Stream Error"; + + ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found"; + ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found"; + ply_error_msg[PlyInfo::E_SHORTFILE ]="Unespected eof"; + ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices"; + ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face"; + ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates"; + ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices"; + } + + if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error"; + else return ply_error_msg[error].c_str(); + }; + + static int GetExportMaskCapability() + { + int capability = 0; + capability |= vcg::tri::io::Mask::IOM_VERTCOORD ; + capability |= vcg::tri::io::Mask::IOM_VERTFLAGS ; + capability |= vcg::tri::io::Mask::IOM_VERTCOLOR ; + capability |= vcg::tri::io::Mask::IOM_VERTQUALITY ; + capability |= vcg::tri::io::Mask::IOM_VERTNORMAL ; + capability |= vcg::tri::io::Mask::IOM_VERTRADIUS ; + capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD ; + capability |= vcg::tri::io::Mask::IOM_FACEINDEX ; + capability |= vcg::tri::io::Mask::IOM_FACEFLAGS ; + capability |= vcg::tri::io::Mask::IOM_FACECOLOR ; + capability |= vcg::tri::io::Mask::IOM_FACEQUALITY ; + // capability |= vcg::tri::io::Mask::IOM_FACENORMAL ; + capability |= vcg::tri::io::Mask::IOM_WEDGCOLOR ; + capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD ; + capability |= vcg::tri::io::Mask::IOM_WEDGTEXMULTI ; + capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL ; + capability |= vcg::tri::io::Mask::IOM_CAMERA ; + //capability |= vcg::tri::io::Mask::IOM_BITPOLYGONAL; + return capability; + } + + +}; // end class - } // end namespace tri - } // end namespace io +} // end namespace tri +} // end namespace io } // end namespace vcg //@} #endif diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index 39144305..47b8754c 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -100,22 +100,66 @@ public: addPerElemScalarAttribute(elemType, vcg::ply::T_DOUBLE, attrName, propName); } - void addPerVertexScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") { + void addPerVertexScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { addPerElemScalarAttribute(0,attrType, attrName,propName); } - void AddPerVertexFloatAttribute(const std::string& attrName, std::string propName="") { + void AddPerVertexFloatAttribute(const std::string& attrName, std::string propName="") + { AddPerElemFloatAttribute(0,attrName,propName); } - void addPerFaceScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") { + void addPerFaceScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { addPerElemScalarAttribute(1,attrType, attrName,propName); } - void AddPerFaceFloatAttribute(const std::string& attrName, std::string propName="") { + void AddPerFaceFloatAttribute(const std::string& attrName, std::string propName="") + { AddPerElemFloatAttribute(1,attrName,propName); } + void addPerElemPointAttribute(int elemType, vcg::ply::PlyTypes propertyType, const std::string& attrName, std::string propName="") + { + if(propName=="") + propName=attrName; + + PropDescriptor p; + p.propname=propName; + p.stotype1 = propertyType; + p.memtype1 = propertyType; + p.islist = true; + p.stotype2 = vcg::ply::PlyTypes::T_UINT; + p.stotype2 = vcg::ply::PlyTypes::T_UINT; + + if (elemType == 0){ //vertex + VertAttrNameVec.push_back(attrName); + p.elemname="vertex"; + VertDescriptorVec.push_back(p); + } + else if (elemType == 1){ //face + FaceAttrNameVec.push_back(attrName); + p.elemname="face"; + FaceDescriptorVec.push_back(p); + } + } + + void addPerVertexPoint3mAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { + addPerElemPointAttribute(0,attrType, attrName,propName); + } + + void addPerVertexPoint3fAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(0,vcg::ply::PlyTypes::T_FLOAT, attrName,propName); + } + + void addPerVertexPoint3dAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(0,vcg::ply::PlyTypes::T_DOUBLE, attrName,propName); + } + /* Note that saving a per vertex point3 attribute is a mess. * Actually require to allocate 3 float attribute and save them. And they are never deallocated... */ template diff --git a/wrap/ply/plylib.cpp b/wrap/ply/plylib.cpp index 8530349f..c4657fd6 100644 --- a/wrap/ply/plylib.cpp +++ b/wrap/ply/plylib.cpp @@ -143,8 +143,12 @@ static int TypeSize[] = { size_t PropDescriptor::memtypesize() const {return TypeSize[memtype1];} size_t PropDescriptor::stotypesize() const {return TypeSize[stotype1];} +size_t PropDescriptor::memtype2size() const {return TypeSize[memtype2];} +size_t PropDescriptor::stotype2size() const {return TypeSize[stotype2];} const char *PropDescriptor::memtypename() const {return PlyFile::typenames[memtype1];} const char *PropDescriptor::stotypename() const {return PlyFile::typenames[stotype1];} +const char *PropDescriptor::memtype2name() const {return PlyFile::typenames[memtype2];} +const char *PropDescriptor::stotype2name() const {return PlyFile::typenames[stotype2];} static char CrossType[9][9]= { diff --git a/wrap/ply/plylib.h b/wrap/ply/plylib.h index 88470b20..36fa757e 100644 --- a/wrap/ply/plylib.h +++ b/wrap/ply/plylib.h @@ -133,6 +133,10 @@ public: size_t memtypesize() const; // per sapere quanto e'grande un dato descrittore in memoria const char* memtypename() const; const char* stotypename() const; + size_t stotype2size() const; // per sapere quanto e'grande un dato descrittore sul file + size_t memtype2size() const; // per sapere quanto e'grande un dato descrittore in memoria + const char* memtype2name() const; + const char* stotype2name() const; }; // Reading Callback (used to copy a data prop) From 702c13910843ea95512146447e36beeb47a8b9eb Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 2 Apr 2021 16:37:10 +0200 Subject: [PATCH 112/140] ply export custom point attribute - set list size to uchar type --- wrap/io_trimesh/export_ply.h | 10 +++++----- wrap/io_trimesh/io_ply.h | 4 ++-- wrap/ply/plylib.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index b5be20ca..0138dba1 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -416,7 +416,7 @@ public: { case ply::T_FLOAT : thff[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; case ply::T_SHORT : thsf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; case ply::T_CHAR : thcf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; @@ -482,7 +482,7 @@ public: { case ply::T_FLOAT : tf=thfv[i][vp]; fwrite(&tf, sizeof(float),1,fpout); break; case ply::T_DOUBLE : td=thdv[i][vp]; fwrite(&td, sizeof(double),1,fpout); break; - case ply::T_INT : ti=thiv[i][vp]; fwrite(&ti, sizeof(int),1,fpout); break; + case ply::T_INT : ti=thiv[i][vp]; fwrite(&ti, sizeof(int),1,fpout); break; case ply::T_SHORT : ts=thsv[i][vp]; fwrite(&ts, sizeof(short),1,fpout); break; case ply::T_CHAR : tc=thcv[i][vp]; fwrite(&tc, sizeof(char),1,fpout); break; case ply::T_UCHAR : tu=thuv[i][vp]; fwrite(&tu,sizeof(unsigned char),1,fpout); break; @@ -490,18 +490,18 @@ public: } } else { //it is a Poin3f or a Point3d attribute. Saving it as a list - static const unsigned int psize = 3; + static const unsigned char psize = 3; switch (pi.VertDescriptorVec[i].stotype1) { case ply::T_FLOAT : - fwrite(&psize, sizeof(unsigned int), 1,fpout); + fwrite(&psize, sizeof(unsigned char), 1,fpout); fwrite(&thp3fv[i][vp][0], sizeof(float), 1,fpout); fwrite(&thp3fv[i][vp][1], sizeof(float), 1,fpout); fwrite(&thp3fv[i][vp][2], sizeof(float), 1,fpout); break; //fprintf(fpout,"%d %f %f %f", 3, thp3fv[i][vp][0], thp3fv[i][vp][1], thp3fv[i][vp][2]); break; case ply::T_DOUBLE : - fwrite(&psize, sizeof(unsigned int), 1,fpout); + fwrite(&psize, sizeof(unsigned char), 1,fpout); fwrite(&thp3dv[i][vp][0], sizeof(double), 1,fpout); fwrite(&thp3dv[i][vp][1], sizeof(double), 1,fpout); fwrite(&thp3dv[i][vp][2], sizeof(double), 1,fpout); diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index 47b8754c..92ba9f2d 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -130,8 +130,8 @@ public: p.stotype1 = propertyType; p.memtype1 = propertyType; p.islist = true; - p.stotype2 = vcg::ply::PlyTypes::T_UINT; - p.stotype2 = vcg::ply::PlyTypes::T_UINT; + p.memtype2 = vcg::ply::PlyTypes::T_UCHAR; + p.stotype2 = vcg::ply::PlyTypes::T_UCHAR; if (elemType == 0){ //vertex VertAttrNameVec.push_back(attrName); diff --git a/wrap/ply/plylib.h b/wrap/ply/plylib.h index 36fa757e..0162ae00 100644 --- a/wrap/ply/plylib.h +++ b/wrap/ply/plylib.h @@ -176,7 +176,7 @@ public: int bestored; // 1 se va storata PropDescriptor desc; // Descrittore di memorizzazione - readelemcb cb; // Callback di lettura + readelemcb cb = nullptr; // Callback di lettura }; From c1d973238161f74f6194f0746454725dd39cc00b Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 2 Apr 2021 17:02:03 +0200 Subject: [PATCH 113/140] support export per face point custom attributes on ply --- wrap/io_trimesh/export_ply.h | 128 +++++++++++++++++++++++++---------- wrap/io_trimesh/io_ply.h | 15 ++++ 2 files changed, 108 insertions(+), 35 deletions(-) diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index 0138dba1..4f120237 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -284,8 +284,24 @@ public: fprintf(fpout,"property %s quality\n",fqtp); } - for(size_t i=0;i0 && (pi.mask & Mask::IOM_EDGEINDEX) ) fprintf( @@ -406,21 +422,33 @@ public: std::vector > thsf(pi.FaceDescriptorVec.size()); std::vector > thcf(pi.FaceDescriptorVec.size()); std::vector > thuf(pi.FaceDescriptorVec.size()); + std::vector > thp3ff(pi.FaceDescriptorVec.size()); + std::vector > thp3df(pi.FaceDescriptorVec.size()); for(size_t i=0;i::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_SHORT : thsf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_CHAR : thcf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - default : assert(0); + if (!pi.FaceDescriptorVec[i].islist) { + switch (pi.FaceDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : thff[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_SHORT : thsf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_CHAR : thcf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + default : assert(0); + } + } + else { + switch (pi.FaceDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : thp3ff[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_DOUBLE : thp3df[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + default : assert(0); + } } } } @@ -579,12 +607,12 @@ public: { switch (pi.VertDescriptorVec[i].memtype1) { - case ply::T_FLOAT : tf=*( (float *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%f ",tf); break; - case ply::T_DOUBLE : td=*( (double *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%lf ",tf); break; - case ply::T_INT : ti=*( (int *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; - case ply::T_SHORT : ti=*( (short *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; - case ply::T_CHAR : ti=*( (char *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; - case ply::T_UCHAR : ti=*( (unsigned char *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; + case ply::T_FLOAT : tf=*( (float *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%f ",tf); break; + case ply::T_DOUBLE : td=*( (double *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%lf ",tf); break; + case ply::T_INT : ti=*( (int *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; + case ply::T_SHORT : ti=*( (short *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; + case ply::T_CHAR : ti=*( (char *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; + case ply::T_UCHAR : ti=*( (unsigned char *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break; default : assert(0); } } @@ -692,15 +720,35 @@ public: if(!pi.FaceAttrNameVec.empty() && !pi.FaceAttrNameVec[i].empty()) { // trying to use named attribute to retrieve the value to store assert(vcg::tri::HasPerFaceAttribute(m,pi.FaceAttrNameVec[i])); - switch (pi.FaceDescriptorVec[i].stotype1) - { - case ply::T_FLOAT : tf=thff[i][fp]; fwrite(&tf, sizeof(float),1,fpout); break; - case ply::T_DOUBLE : td=thdf[i][fp]; fwrite(&td, sizeof(double),1,fpout); break; - case ply::T_INT : ti=thif[i][fp]; fwrite(&ti, sizeof(int),1,fpout); break; - case ply::T_SHORT : ts=thsf[i][fp]; fwrite(&ts, sizeof(short),1,fpout); break; - case ply::T_CHAR : tc=thcf[i][fp]; fwrite(&tc, sizeof(char),1,fpout); break; - case ply::T_UCHAR : tu=thuf[i][fp]; fwrite(&tu,sizeof(unsigned char),1,fpout); break; - default : assert(0); + if (!pi.FaceDescriptorVec[i].islist){ + switch (pi.FaceDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : tf=thff[i][fp]; fwrite(&tf, sizeof(float),1,fpout); break; + case ply::T_DOUBLE : td=thdf[i][fp]; fwrite(&td, sizeof(double),1,fpout); break; + case ply::T_INT : ti=thif[i][fp]; fwrite(&ti, sizeof(int),1,fpout); break; + case ply::T_SHORT : ts=thsf[i][fp]; fwrite(&ts, sizeof(short),1,fpout); break; + case ply::T_CHAR : tc=thcf[i][fp]; fwrite(&tc, sizeof(char),1,fpout); break; + case ply::T_UCHAR : tu=thuf[i][fp]; fwrite(&tu,sizeof(unsigned char),1,fpout); break; + default : assert(0); + } + } + else { + static const unsigned char psize = 3; + switch (pi.FaceDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : + fwrite(&psize, sizeof(unsigned char), 1,fpout); + fwrite(&thp3ff[i][fp][0], sizeof(float), 1,fpout); + fwrite(&thp3ff[i][fp][1], sizeof(float), 1,fpout); + fwrite(&thp3ff[i][fp][2], sizeof(float), 1,fpout); + break; + case ply::T_DOUBLE : + fwrite(&psize, sizeof(unsigned char), 1,fpout); + fwrite(&thp3df[i][fp][0], sizeof(double), 1,fpout); + fwrite(&thp3df[i][fp][1], sizeof(double), 1,fpout); + fwrite(&thp3df[i][fp][2], sizeof(double), 1,fpout); + default : assert(0); + } } } else @@ -777,15 +825,25 @@ public: if(!pi.FaceAttrNameVec.empty() && !pi.FaceAttrNameVec[i].empty()) { // trying to use named attribute to retrieve the value to store assert(vcg::tri::HasPerFaceAttribute(m,pi.FaceAttrNameVec[i])); - switch (pi.FaceDescriptorVec[i].stotype1) - { - case ply::T_FLOAT : tf=thff[i][fp]; fprintf(fpout,"%f ",tf); break; - case ply::T_DOUBLE : td=thdf[i][fp]; fprintf(fpout,"%g ",td); break; - case ply::T_INT : ti=thif[i][fp]; fprintf(fpout,"%i ",ti); break; - case ply::T_SHORT : ti=thsf[i][fp]; fprintf(fpout,"%i ",ti); break; - case ply::T_CHAR : ti=thcf[i][fp]; fprintf(fpout,"%i ",ti); break; - case ply::T_UCHAR : ti=thuf[i][fp]; fprintf(fpout,"%i ",ti); break; - default : assert(0); + if(!pi.FaceDescriptorVec[i].islist) { + switch (pi.FaceDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : tf=thff[i][fp]; fprintf(fpout,"%f ",tf); break; + case ply::T_DOUBLE : td=thdf[i][fp]; fprintf(fpout,"%g ",td); break; + case ply::T_INT : ti=thif[i][fp]; fprintf(fpout,"%i ",ti); break; + case ply::T_SHORT : ti=thsf[i][fp]; fprintf(fpout,"%i ",ti); break; + case ply::T_CHAR : ti=thcf[i][fp]; fprintf(fpout,"%i ",ti); break; + case ply::T_UCHAR : ti=thuf[i][fp]; fprintf(fpout,"%i ",ti); break; + default : assert(0); + } + } + else { + switch (pi.FaceDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : fprintf(fpout,"%d %f %f %f", 3, thp3ff[i][fp][0], thp3ff[i][fp][1], thp3ff[i][fp][2]); break; + case ply::T_DOUBLE : fprintf(fpout,"%d %lf %lf %lf", 3, thp3df[i][fp][0], thp3df[i][fp][1], thp3df[i][fp][2]); break; + default : assert(0); + } } } else diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index 92ba9f2d..05c25cab 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -160,6 +160,21 @@ public: addPerElemPointAttribute(0,vcg::ply::PlyTypes::T_DOUBLE, attrName,propName); } + void addPerFacePoint3mAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { + addPerElemPointAttribute(1,attrType, attrName,propName); + } + + void addPerFacePoint3fAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(1,vcg::ply::PlyTypes::T_FLOAT, attrName,propName); + } + + void addPerFacePoint3dAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(1,vcg::ply::PlyTypes::T_DOUBLE, attrName,propName); + } + /* Note that saving a per vertex point3 attribute is a mess. * Actually require to allocate 3 float attribute and save them. And they are never deallocated... */ template From 0a17efe9a809d2fc82838affe5d0a239e9e546fc Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 7 Apr 2021 13:22:08 +0200 Subject: [PATCH 114/140] missing include import obj --- wrap/io_trimesh/import_obj.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wrap/io_trimesh/import_obj.h b/wrap/io_trimesh/import_obj.h index 9f9fa909..66ce8526 100644 --- a/wrap/io_trimesh/import_obj.h +++ b/wrap/io_trimesh/import_obj.h @@ -25,6 +25,8 @@ #ifndef __VCGLIB_IMPORT_OBJ #define __VCGLIB_IMPORT_OBJ +#include + #include #include #include @@ -1057,8 +1059,8 @@ public: // adding texture name into textures vector (if not already present) // avoid adding the same name twice auto it = std::find(textures.begin(), textures.end(), textureName); - if(it==textures.end()) { - currentMaterial.index = textures.size(); + if(it==textures.end()) { + currentMaterial.index = textures.size(); textures.push_back(textureName); } else { currentMaterial.index = std::distance(textures.begin(),it); @@ -1080,7 +1082,7 @@ public: { materials[i].map_Kd=textures[0]; materials[i].index=0; - } + } } } From 0882d6258252174ee6635b3d1d337bdedad97ab8 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 20 Apr 2021 10:25:54 +0200 Subject: [PATCH 115/140] fix import matrix precision in aln parser --- wrap/io_trimesh/alnParser.h | 192 ++++++++++++++++++------------------ 1 file changed, 95 insertions(+), 97 deletions(-) diff --git a/wrap/io_trimesh/alnParser.h b/wrap/io_trimesh/alnParser.h index 1e7fd4a4..1e18593a 100644 --- a/wrap/io_trimesh/alnParser.h +++ b/wrap/io_trimesh/alnParser.h @@ -2,7 +2,7 @@ * MeshLab o o * * An extendible mesh processor o o * * _ O _ * -* Copyright(C) 2005, 2009 \/)\/ * +* Copyright(C) 2005, 2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -30,126 +30,124 @@ struct RangeMap { - RangeMap() - { - quality = 1.0f; - } + RangeMap() : quality(1.0f) {} - std::string filename; - Matrix44m transformation; - float quality; + std::string filename; + vcg::Matrix44d transformation; + float quality; }; class ALNParser { public: - enum ALNParserCodes {NoError, CantOpen, UnexpectedEOF, ExpectingComment}; + enum ALNParserCodes {NoError, CantOpen, UnexpectedEOF, ExpectingComment}; - static const char* ErrorMsg(int message_code) - { - static const char* error_msg[4] = {"No errors", "Can't open file", "Premature End of file", "I was expecting a comment"}; + static const char* ErrorMsg(int message_code) + { + static const char* error_msg[4] = {"No errors", "Can't open file", "Premature End of file", "I was expecting a comment"}; - if(message_code>3 || message_code<0) - return "Unknown error"; - else - return error_msg[message_code]; - }; + if(message_code>3 || message_code<0) + return "Unknown error"; + else + return error_msg[message_code]; + }; - static int BuildALN(std::vector &rangemaps, std::vector< std::string > &files) - { - rangemaps.clear(); - rangemaps.resize( files.size() ); - std::vector< RangeMap >::iterator rm = rangemaps.begin(); - std::vector< std::string >::iterator it = files.begin(); - std::vector< std::string >::iterator end = files.end(); - for ( ; it!=end; it++, rm++) - { - (*rm).filename = (*it); - (*rm).quality = 1.0f; - (*rm).transformation.SetIdentity(); - } - files.clear(); - return NoError; - }; + static int BuildALN(std::vector &rangemaps, std::vector< std::string > &files) + { + rangemaps.clear(); + rangemaps.resize( files.size() ); + std::vector< RangeMap >::iterator rm = rangemaps.begin(); + std::vector< std::string >::iterator it = files.begin(); + std::vector< std::string >::iterator end = files.end(); + for ( ; it!=end; it++, rm++) + { + (*rm).filename = (*it); + (*rm).quality = 1.0f; + (*rm).transformation.SetIdentity(); + } + files.clear(); + return NoError; + }; - static int ParseALN(std::vector &rangemaps, const char *ALNname) - { - rangemaps.clear(); + static int ParseALN(std::vector &rangemaps, const char *ALNname) + { + rangemaps.clear(); - FILE *stream=fopen(ALNname, "rt"); - if(stream==NULL) - return CantOpen; + FILE *stream=fopen(ALNname, "rt"); + if(stream==NULL) + return CantOpen; - int mesh_number; - fscanf(stream, "%i\n", &mesh_number); + int mesh_number; + fscanf(stream, "%i\n", &mesh_number); - char buffer[1024]; - for (int m=0; m0); + char *occurrence = strchr(buffer, 'W'); + if(occurrence!=NULL && occurrence[1]==':') + rm.quality = (float) atof(occurrence+2); + assert(rm.quality>0); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[0][0]),&(rm.transformation[0][1]),&(rm.transformation[0][2]),&(rm.transformation[0][3])); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[1][0]),&(rm.transformation[1][1]),&(rm.transformation[1][2]),&(rm.transformation[1][3])); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[2][0]),&(rm.transformation[2][1]),&(rm.transformation[2][2]),&(rm.transformation[2][3])); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[3][0]),&(rm.transformation[3][1]),&(rm.transformation[3][2]),&(rm.transformation[3][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[0][0]),&(rm.transformation[0][1]),&(rm.transformation[0][2]),&(rm.transformation[0][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[1][0]),&(rm.transformation[1][1]),&(rm.transformation[1][2]),&(rm.transformation[1][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[2][0]),&(rm.transformation[2][1]),&(rm.transformation[2][2]),&(rm.transformation[2][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[3][0]),&(rm.transformation[3][1]),&(rm.transformation[3][2]),&(rm.transformation[3][3])); - rangemaps.push_back(rm); - } - fclose(stream); - return NoError; - } // end of ParseALN + rangemaps.push_back(rm); + } + fclose(stream); + return NoError; + } // end of ParseALN -static bool SaveALN(const char *alnfile, std::vector &names) -{ - std::vector Tr(names.size()); - for(int i=0; i < static_cast(Tr.size()); ++i) Tr[i].SetIdentity(); - return SaveALN(alnfile,names, Tr); -} -template -static bool SaveALN(const char *alnfile, std::vector &names, std::vector > &Tr) -{ - // printf("Saving aln file %s\n",alnfile); - FILE *fp=fopen(alnfile,"w"); - if(!fp) - { - printf("unable to open file %s\n",alnfile); - return false; - } + static bool SaveALN(const char *alnfile, std::vector &names) + { + std::vector Tr(names.size()); + for(int i=0; i < static_cast(Tr.size()); ++i) Tr[i].SetIdentity(); + return SaveALN(alnfile,names, Tr); + } - fprintf(fp,"%i\n",(int)names.size()); - for(int i=0;i < static_cast(names.size());++i) - { - fprintf(fp,"%s\n",names[i].c_str()); + template + static bool SaveALN(const char *alnfile, std::vector &names, std::vector > &Tr) + { + // printf("Saving aln file %s\n",alnfile); + FILE *fp=fopen(alnfile,"w"); + if(!fp) + { + printf("unable to open file %s\n",alnfile); + return false; + } - fprintf(fp,"#\n"); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][0][0]),(Tr[i][0][1]),(Tr[i][0][2]),(Tr[i][0][3])); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][1][0]),(Tr[i][1][1]),(Tr[i][1][2]),(Tr[i][1][3])); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][2][0]),(Tr[i][2][1]),(Tr[i][2][2]),(Tr[i][2][3])); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][3][0]),(Tr[i][3][1]),(Tr[i][3][2]),(Tr[i][3][3])); - } - fprintf(fp,"0\n"); + fprintf(fp,"%i\n",(int)names.size()); + for(int i=0;i < static_cast(names.size());++i) + { + fprintf(fp,"%s\n",names[i].c_str()); - fclose(fp); - return true; -} + fprintf(fp,"#\n"); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][0][0]),(Tr[i][0][1]),(Tr[i][0][2]),(Tr[i][0][3])); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][1][0]),(Tr[i][1][1]),(Tr[i][1][2]),(Tr[i][1][3])); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][2][0]),(Tr[i][2][1]),(Tr[i][2][2]),(Tr[i][2][3])); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][3][0]),(Tr[i][3][1]),(Tr[i][3][2]),(Tr[i][3][3])); + } + fprintf(fp,"0\n"); + + fclose(fp); + return true; + } }; From 15b1b778d4a260650f3830fdceff028420ce6543 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Thu, 22 Apr 2021 20:49:12 +0200 Subject: [PATCH 116/140] added missing function for polygon face components --- vcg/simplex/face/component_polygon.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index 1fda9d1b..1265b13b 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -143,8 +143,9 @@ public: typename T::FacePointer &VFp(const int j) { assert(j>=0 && jVN()); return _vfpP[j]; } typename T::FacePointer const VFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } typename T::FacePointer const cVFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } - char &VFi(const int j) {return _vfiP[j]; } - char VFi(const int j) const {return _vfiP[j]; } + char & VFi(const int j) { return _vfiP[j]; } + char VFi(const int j) const { return _vfiP[j]; } + char cVFi(const int j) const { return _vfiP[j]; } template void ImportData(const LeftF & leftF){T::ImportData(leftF);} inline void Alloc(const int & ns) { From bd1a92e2f0f5a3b240e5778d816b8e0e7a9e6d1d Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Fri, 23 Apr 2021 16:21:09 +0200 Subject: [PATCH 117/140] fix face flag comments --- vcg/simplex/face/base.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vcg/simplex/face/base.h b/vcg/simplex/face/base.h index 967c7dbc..639d0753 100644 --- a/vcg/simplex/face/base.h +++ b/vcg/simplex/face/base.h @@ -156,7 +156,7 @@ public: /// deletes the Face from the mesh void SetD() {this->Flags() |=DELETED;} - /// un-delete a Face + /// undelete the Face void ClearD() {this->Flags() &=(~DELETED);} /// marks the Face as readable void SetR() {this->Flags() &=(~NOTREAD);} @@ -168,14 +168,14 @@ public: void ClearW() {this->Flags() |=NOTWRITE;} /// select the Face void SetS() {this->Flags() |=SELECTED;} - /// Un-select a Face + /// unselect the Face void ClearS() {this->Flags() &= ~SELECTED;} - /// select the Face + /// set as visited the Face void SetV() {this->Flags() |=VISITED;} - /// Un-select a Face + /// set as unvisited the Face void ClearV() {this->Flags() &= ~VISITED;} - /// This function checks if the face is selected + /// This function checks if the face is border bool IsB(int i) const {return (this->cFlags() & (BORDER0<Flags() |=(BORDER0< Date: Mon, 26 Apr 2021 14:31:04 +0200 Subject: [PATCH 118/140] complex/algorithms/stat.h const correctness --- vcg/complex/algorithms/stat.h | 83 ++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/vcg/complex/algorithms/stat.h b/vcg/complex/algorithms/stat.h index fb2f18b5..f0e8502e 100644 --- a/vcg/complex/algorithms/stat.h +++ b/vcg/complex/algorithms/stat.h @@ -41,64 +41,67 @@ class Stat { public: typedef StatMeshType MeshType; - typedef typename MeshType::ScalarType ScalarType; - typedef typename MeshType::VertexType VertexType; - typedef typename MeshType::VertexPointer VertexPointer; - typedef typename MeshType::VertexIterator VertexIterator; + typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::VertexPointer VertexPointer; + typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::ConstVertexIterator ConstVertexIterator; - typedef typename MeshType::EdgeType EdgeType; - typedef typename MeshType::EdgeIterator EdgeIterator; - typedef typename MeshType::FaceType FaceType; - typedef typename MeshType::FacePointer FacePointer; - typedef typename MeshType::FaceIterator FaceIterator; - typedef typename MeshType::FaceContainer FaceContainer; - typedef typename MeshType::TetraType TetraType; - typedef typename MeshType::TetraPointer TetraPointer; - typedef typename MeshType::TetraIterator TetraIterator; - typedef typename MeshType::TetraContainer TetraContainer; - typedef typename vcg::Box3 Box3Type; + typedef typename MeshType::EdgeType EdgeType; + typedef typename MeshType::EdgeIterator EdgeIterator; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FacePointer FacePointer; + typedef typename MeshType::FaceIterator FaceIterator; + typedef typename MeshType::ConstFaceIterator ConstFaceIterator; + typedef typename MeshType::FaceContainer FaceContainer; + typedef typename MeshType::TetraType TetraType; + typedef typename MeshType::TetraPointer TetraPointer; + typedef typename MeshType::TetraIterator TetraIterator; + typedef typename MeshType::TetraContainer TetraContainer; + typedef typename vcg::Box3 Box3Type; - static void ComputePerVertexQualityMinMax(MeshType & m, ScalarType &minV, ScalarType &maxV) + static void ComputePerVertexQualityMinMax(const MeshType & m, ScalarType &minV, ScalarType &maxV) { std::pair pp = ComputePerVertexQualityMinMax(m); minV=pp.first; maxV=pp.second; } - static std::pair ComputePerVertexQualityMinMax(MeshType & m) + static std::pair ComputePerVertexQualityMinMax(const MeshType & m) { // assert(0); tri::RequirePerVertexQuality(m); - typename MeshType::template PerMeshAttributeHandle < std::pair > mmqH; - mmqH = tri::Allocator::template GetPerMeshAttribute >(m,"minmaxQ"); + /** Please if you need to create an attribute called minmaxQ, implement an + explicit function that does it. This function should take a const Mesh. **/ + //typename MeshType::template PerMeshAttributeHandle < std::pair > mmqH; + //mmqH = tri::Allocator::template GetPerMeshAttribute >(m,"minmaxQ"); std::pair minmax = std::make_pair(std::numeric_limits::max(), -std::numeric_limits::max()); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) { if( (*vi).Q() < minmax.first) minmax.first = (*vi).Q(); if( (*vi).Q() > minmax.second) minmax.second = (*vi).Q(); } - mmqH() = minmax; + //mmqH() = minmax; return minmax; } - static void ComputePerFaceQualityMinMax(MeshType & m, ScalarType &minV, ScalarType &maxV) + static void ComputePerFaceQualityMinMax(const MeshType & m, ScalarType &minV, ScalarType &maxV) { std::pair pp = ComputePerFaceQualityMinMax(m); minV=pp.first; maxV=pp.second; } - static std::pair ComputePerFaceQualityMinMax( MeshType & m) + static std::pair ComputePerFaceQualityMinMax( const MeshType & m) { tri::RequirePerFaceQuality(m); std::pair minmax = std::make_pair(std::numeric_limits::max(),-std::numeric_limits::max()); - FaceIterator fi; + ConstFaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { @@ -141,12 +144,12 @@ public: return avgQ /= (ScalarType) m.TN(); } - static ScalarType ComputePerFaceQualityAvg(MeshType & m) + static ScalarType ComputePerFaceQualityAvg(const MeshType & m) { tri::RequirePerFaceQuality(m); ScalarType AvgQ = 0; - FaceIterator fi; + ConstFaceIterator fi; size_t num=0; for(fi = m.face.begin(); fi != m.face.end(); ++fi) { @@ -221,11 +224,11 @@ public: Works for any triangulated model (no problem with open, nonmanifold selfintersecting models). Useful for computing the barycenter of 2D planar figures. */ - static Point3 ComputeShellBarycenter(MeshType & m) + static Point3 ComputeShellBarycenter(const MeshType & m) { Point3 barycenter(0,0,0); ScalarType areaSum=0; - FaceIterator fi; + ConstFaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { @@ -264,11 +267,11 @@ public: return area/ScalarType(2.0); } - static ScalarType ComputePolyMeshArea(MeshType & m) + static ScalarType ComputePolyMeshArea(const MeshType & m) { ScalarType area=0; - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for(ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) area += PolyArea(*fi); @@ -293,10 +296,10 @@ public: return sum; } - static void ComputePerVertexQualityDistribution(MeshType & m, Distribution & h, bool selectionOnly = false) // V1.0 + static void ComputePerVertexQualityDistribution(const MeshType & m, Distribution & h, bool selectionOnly = false) // V1.0 { tri::RequirePerVertexQuality(m); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) { assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); @@ -304,11 +307,11 @@ public: } } - static void ComputePerFaceQualityDistribution( MeshType & m, Distribution &h, + static void ComputePerFaceQualityDistribution( const MeshType & m, Distribution &h, bool selectionOnly = false) // V1.0 { tri::RequirePerFaceQuality(m); - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for(ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ) { assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); @@ -345,27 +348,27 @@ public: }); } - static void ComputePerFaceQualityHistogram( MeshType & m, Histogram &h, bool selectionOnly=false,int HistSize=10000 ) + static void ComputePerFaceQualityHistogram( const MeshType & m, Histogram &h, bool selectionOnly=false,int HistSize=10000 ) { tri::RequirePerFaceQuality(m); std::pair minmax = tri::Stat::ComputePerFaceQualityMinMax(m); h.Clear(); h.SetRange( minmax.first,minmax.second, HistSize ); - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for(ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ){ assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); h.Add((*fi).Q()); } } - static void ComputePerVertexQualityHistogram( MeshType & m, Histogram &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0 + static void ComputePerVertexQualityHistogram( const MeshType & m, Histogram &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0 { tri::RequirePerVertexQuality(m); std::pair minmax = ComputePerVertexQualityMinMax(m); h.Clear(); h.SetRange( minmax.first,minmax.second, HistSize); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) { assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); @@ -381,7 +384,7 @@ public: { std::vector QV; QV.reserve(m.vn); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) QV.push_back((*vi).Q()); std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end()); @@ -391,7 +394,7 @@ public: h.Clear(); h.SetRange(newmin, newmax, HistSize*50); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) h.Add((*vi).Q()); } From 290ac7a0277b5fc7d999e9c21ab8ca65b2f4db7e Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 7 May 2021 17:25:34 +0200 Subject: [PATCH 119/140] bugfix rotation from between 2 vectors --- vcg/math/matrix33.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vcg/math/matrix33.h b/vcg/math/matrix33.h index 356a10db..c896afca 100644 --- a/vcg/math/matrix33.h +++ b/vcg/math/matrix33.h @@ -523,7 +523,7 @@ Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=t } S dot=(v0*v1); ///control if there is no rotation - if (dot>((S)1-epsilon)) + if (dot>(S(1)-epsilon)) { rotM.SetIdentity(); return rotM; @@ -535,13 +535,13 @@ Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=t //if dot = -1 rotating to opposite vertex //the problem is underdefined, so choose axis such that division is more stable //alternative solution at http://cs.brown.edu/research/pubs/pdfs/1999/Moller-1999-EBA.pdf - if (dot < (S)-1 + epsilon) + if (dot < S(-1) + epsilon) { - S max = std::numeric_limits::min(); + S max = std::numeric_limits::lowest(); int maxInd = 0; for (int i = 0; i < 3; ++i) { - if (v0[i] > max) + if (std::abs(v0[i]) > max) { max = v0[i]; maxInd = i; @@ -552,7 +552,7 @@ Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=t axis[(maxInd+1) % 3] = 0; axis[(maxInd+2) % 3] = 1; - dot = (S)-1; + dot = S(-1); } else { From 1ec2d65a58003c832c0c58b8361d96ea71cf19e4 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Mon, 17 May 2021 10:46:07 +0200 Subject: [PATCH 120/140] fix stl importer for malformed file --- wrap/io_trimesh/import_stl.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/wrap/io_trimesh/import_stl.h b/wrap/io_trimesh/import_stl.h index 8225d13a..df7f4791 100644 --- a/wrap/io_trimesh/import_stl.h +++ b/wrap/io_trimesh/import_stl.h @@ -106,7 +106,7 @@ static bool IsSTLColored(const char * filename, bool &coloredFlag, bool &magicsM coloredFlag=false; magicsMode=false; bool binaryFlag; - if(IsSTLBinary(filename,binaryFlag)==false) + if(IsSTLMalformed(filename,binaryFlag)==false) return false; if(binaryFlag==false) @@ -144,11 +144,12 @@ static bool IsSTLColored(const char * filename, bool &coloredFlag, bool &magicsM return true; } -/* Try to guess if a stl is in binary format - * +/* * return false in case of malformed files + * Try to guess if a stl is in binary format, and sets + * the binaryFlag accordingly */ -static bool IsSTLBinary(const char * filename, bool &binaryFlag) +static bool IsSTLMalformed(const char * filename, bool &binaryFlag) { binaryFlag=false; FILE *fp = fopen(filename, "rb"); @@ -157,8 +158,10 @@ static bool IsSTLBinary(const char * filename, bool &binaryFlag) std::size_t file_size = ftell(fp); unsigned int facenum; /* Check for binary or ASCII file */ - fseek(fp, STL_LABEL_SIZE, SEEK_SET); - fread(&facenum, sizeof(unsigned int), 1, fp); + int ret = fseek(fp, STL_LABEL_SIZE, SEEK_SET); + if (ret != 0) return false; + ret = fread(&facenum, sizeof(unsigned int), 1, fp); + if (ret != 1) return false; std::size_t expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; if(file_size == expected_file_size) @@ -197,7 +200,7 @@ static int Open( OpenMeshType &m, const char * filename, int &loadMask, CallBack fclose(fp); loadMask |= Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; bool binaryFlag; - if(!IsSTLBinary(filename,binaryFlag)) + if(!IsSTLMalformed(filename,binaryFlag)) return E_MALFORMED; if(binaryFlag) return OpenBinary(m,filename,loadMask,cb); From c150c3f6b66edbb21e96d02d373af264b44afdc2 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Mon, 17 May 2021 17:36:32 +0200 Subject: [PATCH 121/140] fix append and SplitManifoldComponents when wedge text coords are enabled --- vcg/complex/algorithms/clean.h | 3 + vcg/complex/append.h | 580 +++++++++++---------------------- 2 files changed, 200 insertions(+), 383 deletions(-) diff --git a/vcg/complex/algorithms/clean.h b/vcg/complex/algorithms/clean.h index cbed0df5..ce4151fc 100644 --- a/vcg/complex/algorithms/clean.h +++ b/vcg/complex/algorithms/clean.h @@ -689,6 +689,9 @@ public: tmpMesh.vert.EnableVFAdjacency(); tmpMesh.face.EnableVFAdjacency(); + if (m.face.IsWedgeTexCoordEnabled()) + tmpMesh.face.EnableWedgeTexCoord(); + size_t selCnt=0; for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 63c44684..0c64e161 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -264,215 +264,7 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, 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 - - Remap remap; - - // 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< PointerToAttribute >::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()) - // //... - // } + MeshAppendConst(ml, mr, selected, adjFlag); } /** @@ -494,180 +286,200 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, * or, use the Mesh function that takes a non-const Right Mesh argument. */ static void MeshAppendConst( - MeshLeft& ml, - const ConstMeshRight& mr, - const bool selected = false, - const bool adjFlag = false) + MeshLeft& ml, + const ConstMeshRight& mr, + const bool selected = false, + const bool adjFlag = false) { - // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr - // and build the remapping for all + // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr + // and build the remapping for all - Remap remap; + Remap remap; - // 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); + // 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); - ForEachVertex(mr, [&](const VertexRight& v) - { - if(!selected || v.IsS()) - { - size_t ind=Index(mr,v); - 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); + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()) + { + size_t ind=Index(mr,v); + 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); - ForEachEdge(mr, [&](const EdgeRight& e) - { - if(!selected || e.IsS()){ - size_t ind=Index(mr,e); - remap.edge[ind]=int(Index(ml,*ep)); - ++ep; - } - }); + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ + size_t ind=Index(mr,e); + 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); + // 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); - ForEachFace(mr, [&](const FaceRight& f) - { - if(!selected || f.IsS()){ - size_t ind=Index(mr,f); - remap.face[ind]=int(Index(ml,*fp)); - ++fp; - } - }); + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()){ + size_t ind=Index(mr,f); + remap.face[ind]=int(Index(ml,*fp)); + ++fp; + } + }); - // hedge - remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); + // hedge + remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); - ForEachHEdge(mr, [&](const HEdgeRight& he) - { - if(!selected || he.IsS()){ - size_t ind=Index(mr,he); - assert(remap.hedge[ind]==Remap::InvalidIndex()); - HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); - (*hp).ImportData(he); - remap.hedge[ind]=Index(ml,*hp); - } - }); + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ + size_t ind=Index(mr,he); + assert(remap.hedge[ind]==Remap::InvalidIndex()); + HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); + (*hp).ImportData(he); + remap.hedge[ind]=Index(ml,*hp); + } + }); - remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); + remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); - ForEachTetra(mr, [&](const TetraRight& t) - { - if (!selected || t.IsS()) { - size_t idx = Index(mr, t); - assert (remap.tetra[idx] == Remap::InvalidIndex()); - TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); - (*tp).ImportData(t); - remap.tetra[idx] = Index(ml, *tp); - } - }); + ForEachTetra(mr, [&](const TetraRight& t) + { + if (!selected || t.IsS()) { + size_t idx = Index(mr, t); + assert (remap.tetra[idx] == Remap::InvalidIndex()); + TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); + (*tp).ImportData(t); + remap.tetra[idx] = Index(ml, *tp); + } + }); - // phase 2. - // copy data from mr to its corresponding elements in ml and adjacencies + // phase 1.5 + // manage textures, creating a new one only when necessary + // (not making unuseful duplicates on append) and save a mapping - // vertex - ForEachVertex(mr, [&](const VertexRight& v) - { - if(!selected || v.IsS()){ - ml.vert[remap.vert[Index(mr,v)]].ImportData(v); - if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,remap); - } - }); + // for each texture in the right mesh, it maps it to the texture index in the + // left mesh + std::vector mappingTextures(mr.textures.size()); - // edge - ForEachEdge(mr, [&](const EdgeRight& e) - { - if(!selected || e.IsS()){ - ml.edge[remap.edge[Index(mr,e)]].ImportData(e); - // Edge to Vertex Adj - EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; - if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){ - el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]]; - el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]]; - } - if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap); - } - }); + unsigned int baseMlT = ml.textures.size(); + for (unsigned int i = 0; i < mr.textures.size(); ++i) { + auto it = std::find(ml.textures.begin(), ml.textures.end(), mr.textures[i]); + //if the right texture does not exists in the left mesh + if (it == ml.textures.end()) { + //add the texture in the left mesh and create the mapping + mappingTextures[i] = baseMlT++; + ml.textures.push_back(mr.textures[i]); + } + else { + //the ith right texture will map in the texture found in the left mesh + mappingTextures[i] = it - ml.textures.begin(); + } + } + //ml.textures.insert(ml.textures.end(), mr.textures.begin(),mr.textures.end()); - // face - const size_t textureOffset = ml.textures.size(); - bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0); - ForEachFace(mr, [&](const FaceRight& f) - { - if(!selected || f.IsS()) - { - FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; - fl.Alloc(f.VN()); - if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ - for(int i = 0; i < fl.VN(); ++i) - fl.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; - } - fl.ImportData(f); - 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,f)]],f,remap); + // phase 2. + // copy data from mr to its corresponding elements in ml and adjacencies - } - }); + // vertex + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()){ + ml.vert[remap.vert[Index(mr,v)]].ImportData(v); + if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,remap); + } + }); - // hedge - ForEachHEdge(mr, [&](const HEdgeRight& he) - { - if(!selected || he.IsS()){ - ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); - ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); - } - }); + // edge + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ + ml.edge[remap.edge[Index(mr,e)]].ImportData(e); + // Edge to Vertex Adj + EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; + if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){ + el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]]; + el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]]; + } + if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap); + } + }); - //tetra - ForEachTetra(mr, [&](const TetraRight& t) - { - if(!selected || t.IsS()) - { - TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; + // face + bool WTFlag = HasPerWedgeTexCoord(mr); + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()) + { + FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; + fl.Alloc(f.VN()); + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < fl.VN(); ++i) + fl.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; + } + fl.ImportData(f); + if(WTFlag) + for(int i = 0; i < fl.VN(); ++i) + fl.WT(i).n() = mappingTextures[f.WT(i).n()]; + if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap); - if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ - for(int i = 0; i < 4; ++i) - tl.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]]; - } - tl.ImportData(t); - if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); + } + }); - } - }); + // hedge + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ + ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); + ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); + } + }); - // phase 3. - // take care of other per mesh data: textures, attributes + //tetra + ForEachTetra(mr, [&](const TetraRight& t) + { + if(!selected || t.IsS()) + { + TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; - // At the end concatenate the vector with texture names. - ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end()); + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < 4; ++i) + tl.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]]; + } + tl.ImportData(t); + if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); - // 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 + } + }); + + // phase 3. + // take care of other per mesh data: attributes + + // 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< PointerToAttribute >::iterator al, ar; @@ -740,40 +552,42 @@ static void MeshAppendConst( } } - // 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()) - // //... - // } + // 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 Copy the second mesh over the first one. - The first mesh is destroyed. If requested only the selected elements are copied. -*/ +/** + * \brief Copy the second mesh over the first one. + * The first mesh is destroyed. If requested only the selected elements are copied. + */ static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) { - ml.Clear(); - Mesh(ml,mr,selected,adjFlag); - ml.bbox.Import(mr.bbox); + ml.Clear(); + Mesh(ml,mr,selected,adjFlag); + ml.bbox.Import(mr.bbox); } static void MeshCopyConst(MeshLeft& ml, const ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) { - ml.Clear(); - MeshAppendConst(ml,mr,selected,adjFlag); - ml.bbox.Import(mr.bbox); + ml.Clear(); + MeshAppendConst(ml,mr,selected,adjFlag); + ml.bbox.Import(mr.bbox); } -/*! \brief %Append only the selected elements of second mesh to the first one. - - It is just a wrap of the main Append::Mesh() - */ +/** + * \brief %Append only the selected elements of second mesh to the first one. + * + * It is just a wrap of the main Append::Mesh() + */ static void Selected(MeshLeft& ml, ConstMeshRight& mr) { - Mesh(ml,mr,true); + Mesh(ml,mr,true); } }; // end of class Append From 5c0ea8b20ea95adfc3a443ef60e02ee54057ec41 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 19 May 2021 16:08:09 +0200 Subject: [PATCH 122/140] update cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc28d096..e7073ae0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Copyright 2019, 2021, Visual Computing Lab, ISTI - Italian National Research Council # SPDX-License-Identifier: BSL-1.0 -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.10) project(VCGLib) # Eigen options From d47e157f687f32bf89b96f1fc64c5b7a053eee37 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 25 May 2021 11:05:38 +0200 Subject: [PATCH 123/140] remove cmake POLICY CMP0072 --- CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7073ae0..663c74cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,11 +16,6 @@ option(VCG_BUILD_EXAMPLES "Build a set of examples of the library" OFF) set (VCG_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}) set (VCG_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE) -# Prefer GLVND -if(POLICY CMP0072) - cmake_policy(SET CMP0072 NEW) -endif() - ### Build settings set(CMAKE_CXX_STANDARD 11) From 7006311807bd09cbc5da2f8d959c81c6b37ceade Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 3 Jun 2021 11:07:15 +0200 Subject: [PATCH 124/140] fix append when mesh has texcoords but not textures --- vcg/complex/append.h | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 0c64e161..2d342038 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -401,11 +401,24 @@ static void MeshAppendConst( // copy data from mr to its corresponding elements in ml and adjacencies // vertex + bool vertTexFlag = HasPerVertexTexCoord(mr); ForEachVertex(mr, [&](const VertexRight& v) { if(!selected || v.IsS()){ - ml.vert[remap.vert[Index(mr,v)]].ImportData(v); - if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,remap); + VertexLeft &vl = ml.vert[remap.vert[Index(mr,v)]]; + vl.ImportData(v); + if(adjFlag) + ImportVertexAdj(ml,mr,vl,v,remap); + if (vertTexFlag){ + if (v.T().n() < mappingTextures.size()) { + //standard case: the texture is contained in the mesh + vl.T().n() = mappingTextures[v.T().n()]; + } + else { + //the mesh has tex coords, but not the texture... + vl.T().n() = v.T().n(); + } + } } }); @@ -425,7 +438,7 @@ static void MeshAppendConst( }); // face - bool WTFlag = HasPerWedgeTexCoord(mr); + bool wedgeTexFlag = HasPerWedgeTexCoord(mr); ForEachFace(mr, [&](const FaceRight& f) { if(!selected || f.IsS()) @@ -437,9 +450,18 @@ static void MeshAppendConst( fl.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; } fl.ImportData(f); - if(WTFlag) - for(int i = 0; i < fl.VN(); ++i) - fl.WT(i).n() = mappingTextures[f.WT(i).n()]; + if(wedgeTexFlag) { + for(int i = 0; i < fl.VN(); ++i){ + if (f.WT(i).n() < mappingTextures.size()){ + //standard case: the texture is contained in the mesh + fl.WT(i).n() = mappingTextures[f.WT(i).n()]; + } + else { + //the mesh has tex coords, but not the texture... + fl.WT(i).n() = f.WT(i).n(); + } + } + } if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap); } From a2735f6da4d2ee7afe85d209fd7d15a75e5e367b Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Mon, 7 Jun 2021 11:33:08 +0200 Subject: [PATCH 125/140] missing include shot qt --- wrap/qt/shot_qt.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wrap/qt/shot_qt.h b/wrap/qt/shot_qt.h index e2dc32e4..e9ca0a6c 100644 --- a/wrap/qt/shot_qt.h +++ b/wrap/qt/shot_qt.h @@ -1,6 +1,10 @@ #ifndef SHOT_QT_H #define SHOT_QT_H +#include +#include + +#include /** This function read a shot from a parsed XML node. From 85d66654308a4ab80068cad36a41cfe080728ad6 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 8 Jun 2021 10:40:30 +0200 Subject: [PATCH 126/140] import_nvm - using std::cerr to remove ambiguous << operator on qDebug --- wrap/io_trimesh/import_nvm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wrap/io_trimesh/import_nvm.h b/wrap/io_trimesh/import_nvm.h index 06f70ac5..8991855a 100644 --- a/wrap/io_trimesh/import_nvm.h +++ b/wrap/io_trimesh/import_nvm.h @@ -166,17 +166,17 @@ static int Open( OpenMeshType &m, std::vector > & shots, float x,y,z; unsigned int r,g,b,i_cam, key_sift,n_corr; uint readValues = fscanf(fp,"%f %f %f ",&x,&y,&z); - if (readValues < 3) qDebug() << "Point " << i << ": only " << readValues << " coordinates read!"; + if (readValues < 3) std::cerr << "Point " << i << ": only " << readValues << " coordinates read!"; (*vi).P() = vcg::Point3(x,y,z); readValues = fscanf(fp,"%d %d %d ",&r,&g,&b); - if (readValues < 3) qDebug() << "Point " << i << ": only " << readValues << " color values read!"; + if (readValues < 3) std::cerr << "Point " << i << ": only " << readValues << " color values read!"; (*vi).C() = vcg::Color4b(r,g,b,255); readValues = fscanf(fp,"%d ",&n_corr); - if (readValues < 1) qDebug() << "Point " << i << ": no n correspondences read!"; + if (readValues < 1) std::cerr << "Point " << i << ": no n correspondences read!"; for(uint j = 0; j < n_corr; ++j){ readValues = fscanf(fp,"%d %d %f %f ",&i_cam,&key_sift,&x,&y); - if (readValues != 3) qDebug() << "Point " << i << "; Corresp: " << j << ": only " << readValues << " values read!"; + if (readValues != 3) std::cerr << "Point " << i << "; Corresp: " << j << ": only " << readValues << " values read!"; Correspondence corr(i_cam,key_sift,x,y); ch[i].push_back(corr); } From 7d5d2271e6f5113c698a23320b2751638c945742 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 11 Jun 2021 16:40:48 +0200 Subject: [PATCH 127/140] fixed gl picking --- wrap/gl/pick.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wrap/gl/pick.h b/wrap/gl/pick.h index bb4ea942..33461bb5 100644 --- a/wrap/gl/pick.h +++ b/wrap/gl/pick.h @@ -26,7 +26,8 @@ #include #include -#include "gl_type_name.h" + +#include namespace vcg{ @@ -218,11 +219,11 @@ public: int screenW = (int)(vp[2]-vp[0]); int screenH = (int)(vp[3]-vp[1]); - GL_TYPE_NM::ScalarType *buffer = new GL_TYPE_NM::ScalarType[screenW*screenH]; + GLfloat *buffer = new GLfloat[screenW*screenH]; - //I'm not sure glReadPixels can accept GL_DOUBLE tag + //glReadPixels does NOT accept GL_DOUBLE //GLenum err = glGetError(); - glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_TYPE_NM::SCALAR(),buffer); + glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); //err = glGetError(); std::vector result; PickFace(x,y,m,result,width,height); @@ -261,11 +262,10 @@ public: int screenH = vp[3]-vp[1]; - GL_TYPE_NM::ScalarType *buffer = new GL_TYPE_NM::ScalarType[screenW*screenH]; + GLfloat *buffer = new GLfloat[screenW*screenH]; - //I'm not sure glReadPixels can accept GL_DOUBLE tag //GLenum err = glGetError(); - glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_TYPE_NM::SCALAR(),buffer); + glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); //err = glGetError(); std::vector result; From 4b8f73d81c6a3fe3c53b55268b94e892b928d394 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 11 Jun 2021 17:28:26 +0200 Subject: [PATCH 128/140] refactoring --- vcg/complex/algorithms/curve_on_manifold.h | 2 +- wrap/gl/pick.h | 529 +++++++-------------- 2 files changed, 174 insertions(+), 357 deletions(-) diff --git a/vcg/complex/algorithms/curve_on_manifold.h b/vcg/complex/algorithms/curve_on_manifold.h index 2c8e4abe..e03e1f5f 100644 --- a/vcg/complex/algorithms/curve_on_manifold.h +++ b/vcg/complex/algorithms/curve_on_manifold.h @@ -1141,7 +1141,7 @@ public: } }; -struct EdgePointSplit : public std::unary_function , CoordType> +struct EdgePointSplit { public: std::map, VertexPointer> &edgeToPolyVertMap; diff --git a/wrap/gl/pick.h b/wrap/gl/pick.h index 33461bb5..4d327d14 100644 --- a/wrap/gl/pick.h +++ b/wrap/gl/pick.h @@ -24,403 +24,220 @@ #ifndef __PICK______H #define __PICK______H +// Assumes OpenGL already included + #include #include #include - namespace vcg{ template class GLPickTri { - typedef typename MESH_TYPE::ScalarType ScalarType; - typedef typename MESH_TYPE::CoordType CoordType; - typedef typename MESH_TYPE::FaceIterator FaceIterator; - typedef typename MESH_TYPE::VertexIterator VertexIterator; - typedef typename MESH_TYPE::FacePointer FacePointer; - typedef typename MESH_TYPE::VertexPointer VertexPointer; - typedef typename MESH_TYPE::VertexType VertexType; - public: - static CoordType glProject(const Eigen::Matrix &M, const ScalarType * viewport, const CoordType &p) - { - const ScalarType vx=viewport[0]; - const ScalarType vy=viewport[1]; - const ScalarType vw2=viewport[2]/ScalarType(2.0); - const ScalarType vh2=viewport[3]/ScalarType(2.0); - Eigen::Matrix vp(p[0],p[1],p[2],ScalarType(1.0)); - Eigen::Matrix vpp = M*vp; - Eigen::Matrix ndc = vpp/vpp[3]; + typedef typename MESH_TYPE::ScalarType ScalarType; + typedef typename MESH_TYPE::CoordType CoordType; + typedef typename MESH_TYPE::FaceIterator FaceIterator; + typedef typename MESH_TYPE::VertexIterator VertexIterator; + typedef typename MESH_TYPE::FacePointer FacePointer; + typedef typename MESH_TYPE::VertexPointer VertexPointer; + typedef typename MESH_TYPE::VertexType VertexType; - CoordType sc( - vw2*ndc[0] + vx+vw2, - vh2*ndc[1] + vy+vh2, - ndc[2] - ); + static CoordType glProject(const Eigen::Matrix &M, const ScalarType * viewport, const CoordType &p) + { + const ScalarType vx=viewport[0]; + const ScalarType vy=viewport[1]; + const ScalarType vw2=viewport[2]/ScalarType(2.0); + const ScalarType vh2=viewport[3]/ScalarType(2.0); + Eigen::Matrix vp(p[0],p[1],p[2],ScalarType(1.0)); + Eigen::Matrix vpp = M*vp; + Eigen::Matrix ndc = vpp/vpp[3]; - return sc; - } + CoordType sc(vw2*ndc[0] + vx+vw2, + vh2*ndc[1] + vy+vh2, + ndc[2]); - static void FillProjectedVector(MESH_TYPE &m, std::vector &pVec, const Eigen::Matrix &M, const ScalarType * viewportF) - { - pVec.resize(m.vert.size()); - for(size_t i=0;i::glProject(M, viewportF,CoordType::Construct(m.vert[i].P())); - } - } + return sc; + } - static void glGetMatrixAndViewport(Eigen::Matrix &M, ScalarType *viewportF) - { - Eigen::Matrix4d mp,mm; + static void FillProjectedVector(MESH_TYPE &m, std::vector &pVec, const Eigen::Matrix &M, const ScalarType * viewportF) + { + pVec.resize(m.vert.size()); + for(size_t i=0;i::glProject(M, viewportF,CoordType::Construct(m.vert[i].P())); + } + } - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - for(int i=0;i<4;++i) viewportF[i]=viewport[i]; + static void glGetMatrixAndViewport(Eigen::Matrix &M, ScalarType *viewportF) + { + Eigen::Matrix4d mp,mm; - glGetDoublev(GL_PROJECTION_MATRIX, mp.data()); - glGetDoublev(GL_MODELVIEW_MATRIX, mm.data()); + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT,viewport); + for(int i=0;i<4;++i) viewportF[i]=viewport[i]; - M = (mp*mm).cast(); - } + glGetDoublev(GL_PROJECTION_MATRIX, mp.data()); + glGetDoublev(GL_MODELVIEW_MATRIX, mm.data()); - // compute a bbox in Device Coordinate (with the z without the near far normalization and ranged in -1 1) - static Box3 ComputeDCBox(int x, int y, int width, int height) - { - Box3 bb; - bb.SetNull(); - bb.Add(CoordType(x-width/ScalarType(2.0),y-height/ScalarType(2.0),ScalarType(-1.0))); - bb.Add(CoordType(x+width/ScalarType(2.0),y+height/ScalarType(2.0), ScalarType(1.0))); - return bb; - } + M = (mp*mm).cast(); + } -public: + // compute a bbox in Device Coordinate (with the z without the near far normalization and ranged in -1 1) + static Box3 ComputeDCBox(int x, int y, int width, int height) + { + Box3 bb; + bb.SetNull(); + bb.Add(CoordType(x-width/ScalarType(2.0),y-height/ScalarType(2.0),ScalarType(-1.0))); + bb.Add(CoordType(x+width/ScalarType(2.0),y+height/ScalarType(2.0), ScalarType(1.0))); + return bb; + } - static bool PickClosestFace(int x, int y, MESH_TYPE &m, FacePointer &fp,int width=4, int height=4) - { - Eigen::Matrix M; - ScalarType viewportF[4]; - glGetMatrixAndViewport(M,viewportF); - Box3 reg=ComputeDCBox(x,y,width,height); + static bool PickClosestFace(int x, int y, MESH_TYPE &m, FacePointer &fp,int width=4, int height=4) + { + Eigen::Matrix M; + ScalarType viewportF[4]; + glGetMatrixAndViewport(M,viewportF); + Box3 reg=ComputeDCBox(x,y,width,height); - ScalarType bzmin = std::numeric_limits::max(); - fp=0; - for(size_t i=0;i::max(); + fp=0; + for(size_t i=0;i M; - ScalarType viewportF[4]; - glGetMatrixAndViewport(M,viewportF); - ScalarType bzmin = std::numeric_limits::max(); - vp=0; + static bool PickClosestVert(int x, int y, MESH_TYPE &m, VertexPointer &vp,int width=4, int height=4) + { + Eigen::Matrix M; + ScalarType viewportF[4]; + glGetMatrixAndViewport(M,viewportF); + ScalarType bzmin = std::numeric_limits::max(); + vp=0; - Box3 reg=ComputeDCBox(x,y,width,height); + Box3 reg=ComputeDCBox(x,y,width,height); - for(size_t i=0;i &result, int width=4, int height=4) - { - result.clear(); - static Eigen::Matrix lastM; - static MESH_TYPE *lastm=0; - static std::vector pVec; + static int PickVert(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4) + { + result.clear(); + static Eigen::Matrix lastM; + static MESH_TYPE *lastm=0; + static std::vector pVec; - Eigen::Matrix M; - ScalarType viewportF[4]; - glGetMatrixAndViewport(M,viewportF); + Eigen::Matrix M; + ScalarType viewportF[4]; + glGetMatrixAndViewport(M,viewportF); - Box3 reg =ComputeDCBox(x,y,width,height); + Box3 reg =ComputeDCBox(x,y,width,height); - if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) - { - FillProjectedVector(m,pVec,M,viewportF); - lastM = M; - lastm = &m; - } + if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) + { + FillProjectedVector(m,pVec,M,viewportF); + lastM = M; + lastm = &m; + } - for(size_t i=0;i &result, int width = 4, int height = 4) - { - static Eigen::Matrix lastM; - static MESH_TYPE *lastm = 0; - static std::vector pVec; + static int PickFace(int x, int y, MESH_TYPE &m, std::vector &result, int width = 4, int height = 4) + { + static Eigen::Matrix lastM; + static MESH_TYPE *lastm = 0; + static std::vector pVec; - ScalarType viewportF[4]; - Eigen::Matrix M; - glGetMatrixAndViewport(M, viewportF); - result.clear(); - Box3 reg; - reg.Add(CoordType(x - width / ScalarType(2.0), y - height / ScalarType(2.0), ScalarType(-1.0))); - reg.Add(CoordType(x + width / ScalarType(2.0), y + height / ScalarType(2.0), ScalarType(1.0))); + ScalarType viewportF[4]; + Eigen::Matrix M; + glGetMatrixAndViewport(M, viewportF); + result.clear(); + Box3 reg; + reg.Add(CoordType(x - width / ScalarType(2.0), y - height / ScalarType(2.0), ScalarType(-1.0))); + reg.Add(CoordType(x + width / ScalarType(2.0), y + height / ScalarType(2.0), ScalarType(1.0))); - - if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) - { - FillProjectedVector(m, pVec, M, viewportF); - lastM = M; - lastm = &m; - } + if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) + { + FillProjectedVector(m, pVec, M, viewportF); + lastM = M; + lastm = &m; + } - for (size_t i = 0; i < m.face.size(); ++i) - { - if (!m.face[i].IsD()) - { - const CoordType &p0 = pVec[tri::Index(m, m.face[i].V(0))]; - const CoordType &p1 = pVec[tri::Index(m, m.face[i].V(1))]; - const CoordType &p2 = pVec[tri::Index(m, m.face[i].V(2))]; + for (size_t i = 0; i < m.face.size(); ++i) + { + if (!m.face[i].IsD()) + { + const CoordType &p0 = pVec[tri::Index(m, m.face[i].V(0))]; + const CoordType &p1 = pVec[tri::Index(m, m.face[i].V(1))]; + const CoordType &p2 = pVec[tri::Index(m, m.face[i].V(2))]; - if (!(abs(p0[2]) > 1 || abs(p1[2]) > 1 || abs(p2[2]) > 1) && IntersectionTriangleBox(reg, p0, p1, p2)) - result.push_back(&m.face[i]); - } - } - return result.size(); - } + if (!(abs(p0[2]) > 1 || abs(p1[2]) > 1 || abs(p2[2]) > 1) && IntersectionTriangleBox(reg, p0, p1, p2)) + result.push_back(&m.face[i]); + } + } + return result.size(); + } - // Same of above but it also assumes that you want only visible faces. - // Visibility is computed according to the current depth buffer. - static int PickVisibleFace(int x, int y, MESH_TYPE &m, std::vector &resultZ, int width=4, int height=4) - { - ScalarType vp[4]; - Eigen::Matrix M; - glGetMatrixAndViewport(M,vp); + // Same of above but it also assumes that you want only visible faces. + // Visibility is computed according to the current depth buffer. + static int PickVisibleFace(int x, int y, MESH_TYPE &m, std::vector &resultZ, int width=4, int height=4) + { + ScalarType vp[4]; + Eigen::Matrix M; + glGetMatrixAndViewport(M,vp); - int screenW = (int)(vp[2]-vp[0]); - int screenH = (int)(vp[3]-vp[1]); + int screenW = (int)(vp[2]-vp[0]); + int screenH = (int)(vp[3]-vp[1]); - GLfloat *buffer = new GLfloat[screenW*screenH]; + GLfloat *buffer = new GLfloat[screenW*screenH]; - //glReadPixels does NOT accept GL_DOUBLE - //GLenum err = glGetError(); - glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); - //err = glGetError(); - std::vector result; - PickFace(x,y,m,result,width,height); - ScalarType LocalEpsilon(ScalarType(0.001)); - for(size_t i =0;i=0 && p[0]=0 && p[1]= ScalarType(p[2]+1.0)/2.0) - resultZ.push_back(result[i]); - } - } + //glReadPixels does NOT accept GL_DOUBLE + //GLenum err = glGetError(); + glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); + //err = glGetError(); + std::vector result; + PickFace(x,y,m,result,width,height); + ScalarType LocalEpsilon(ScalarType(0.001)); + for(size_t i =0;i=0 && p[0]=0 && p[1]= ScalarType(p[2]+1.0)/2.0) + resultZ.push_back(result[i]); + } + } - delete [] buffer; - return resultZ.size(); - } - - -#ifdef _I_REALLY_NEED_OLD_GL_PICK_ - // Same of above but it also assumes that you want only visible faces. - // Visibility is computed according to the current depth buffer. - static int OldPickFaceVisible(int x, int y, MESH_TYPE &m, std::vector &resultZ, int width=4, int height=4, bool sorted=true) - { - // First step - - double mm[16]; - double mp[16]; - GLint vp[4]; - glGetIntegerv(GL_VIEWPORT,vp); - glGetDoublev(GL_MODELVIEW_MATRIX ,mm); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - int screenW = vp[2]-vp[0]; - int screenH = vp[3]-vp[1]; - - - GLfloat *buffer = new GLfloat[screenW*screenH]; - - //GLenum err = glGetError(); - glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); - //err = glGetError(); - - std::vector result; - OldPickFace(x,y,m,result,width,height,sorted); - ScalarType LocalEpsilon(0.001); - for(size_t i =0;i=0 && tx=0 && ty= tz) - resultZ.push_back(result[i]); - } - } - - delete [] buffer; - return resultZ.size(); - } - - static int OldPickFace(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4,bool sorted=true) - { - result.clear(); - if(width==0 ||height==0) return 0; - long hits; - int sz=m.face.size()*5; - GLuint *selectBuf =new GLuint[sz]; - // static unsigned int selectBuf[16384]; - glSelectBuffer(sz, selectBuf); - glRenderMode(GL_SELECT); - glInitNames(); - - /* Because LoadName() won't work with no names on the stack */ - glPushName(-1); - double mp[16]; - - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - glMatrixMode(GL_PROJECTION); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - glPushMatrix(); - glLoadIdentity(); - //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); - gluPickMatrix(x, y, width, height, viewport); - glMultMatrixd(mp); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - int fcnt=0; - FaceIterator fi; - for(fi=m.face.begin();fi!=m.face.end();++fi) - { - if(!(*fi).IsD()) - { - glLoadName(fcnt); - glBegin(GL_TRIANGLES); - glVertex( (*fi).V(0)->P() ); - glVertex( (*fi).V(1)->P() ); - glVertex( (*fi).V(2)->P() ); - glEnd(); - } - fcnt++; // the counter should advance even for deleted faces! - } - - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - hits = glRenderMode(GL_RENDER); - //xstring buf; - //if (hits <= 0) return 0; - std::vector< std::pair > H; - for(long ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); - } - if(sorted) - std::sort(H.begin(),H.end()); - // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); - result.resize(H.size()); - for(long ii=0;ii &result, int width=4, int height=4,bool sorted=true) - { - result.clear(); - if(width==0 ||height==0) return 0; - long hits; - int sz=m.vert.size()*5; - GLuint *selectBuf =new GLuint[sz]; - glSelectBuffer(sz, selectBuf); - glRenderMode(GL_SELECT); - glInitNames(); - - /* Because LoadName() won't work with no names on the stack */ - glPushName(-1); - double mp[16]; - - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - glMatrixMode(GL_PROJECTION); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - glPushMatrix(); - glLoadIdentity(); - gluPickMatrix(x, y, width, height, viewport); - glMultMatrixd(mp); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - int vcnt=0; - VertexIterator vi; - for(vi=m.vert.begin();vi!=m.vert.end();++vi) - { - if(!(*vi).IsD()) - { - glLoadName(vcnt); - glBegin(GL_POINTS); - glVertex( (*vi).P() ); - glEnd(); - } - vcnt++; // the counter should advance even for deleted faces! - } - - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - hits = glRenderMode(GL_RENDER); - std::vector< std::pair > H; - for(long ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); - } - if(sorted) - std::sort(H.begin(),H.end()); - result.resize(H.size()); - for(long ii=0;ii Date: Tue, 15 Jun 2021 12:27:04 +0200 Subject: [PATCH 129/140] update eigen to 3.3.9 --- eigenlib/Eigen/Cholesky | 5 + eigenlib/Eigen/Core | 40 +- eigenlib/Eigen/Eigenvalues | 8 +- eigenlib/Eigen/Geometry | 4 +- eigenlib/Eigen/LU | 4 + eigenlib/Eigen/QR | 8 +- eigenlib/Eigen/QtAlignedMalloc | 6 +- eigenlib/Eigen/SVD | 4 + eigenlib/Eigen/Sparse | 2 + eigenlib/Eigen/SparseQR | 1 - eigenlib/Eigen/StdDeque | 2 +- eigenlib/Eigen/StdList | 2 +- eigenlib/Eigen/StdVector | 2 +- eigenlib/Eigen/src/Cholesky/LDLT.h | 14 +- eigenlib/Eigen/src/Cholesky/LLT.h | 26 +- eigenlib/Eigen/src/Core/Array.h | 10 +- eigenlib/Eigen/src/Core/ArrayBase.h | 12 +- eigenlib/Eigen/src/Core/ArrayWrapper.h | 6 +- eigenlib/Eigen/src/Core/AssignEvaluator.h | 33 +- eigenlib/Eigen/src/Core/Assign_MKL.h | 6 +- eigenlib/Eigen/src/Core/ConditionEstimator.h | 2 +- eigenlib/Eigen/src/Core/CoreEvaluators.h | 43 +- eigenlib/Eigen/src/Core/CwiseNullaryOp.h | 80 +- eigenlib/Eigen/src/Core/CwiseUnaryView.h | 2 + eigenlib/Eigen/src/Core/DenseBase.h | 27 +- eigenlib/Eigen/src/Core/DenseStorage.h | 35 +- eigenlib/Eigen/src/Core/Diagonal.h | 7 +- eigenlib/Eigen/src/Core/Dot.h | 17 +- eigenlib/Eigen/src/Core/EigenBase.h | 4 + eigenlib/Eigen/src/Core/GeneralProduct.h | 21 +- eigenlib/Eigen/src/Core/GenericPacketMath.h | 15 +- eigenlib/Eigen/src/Core/IO.h | 14 - eigenlib/Eigen/src/Core/Map.h | 17 +- eigenlib/Eigen/src/Core/MapBase.h | 11 +- eigenlib/Eigen/src/Core/MathFunctions.h | 95 +-- eigenlib/Eigen/src/Core/MathFunctionsImpl.h | 23 + eigenlib/Eigen/src/Core/Matrix.h | 2 - eigenlib/Eigen/src/Core/MatrixBase.h | 42 +- eigenlib/Eigen/src/Core/NumTraits.h | 2 + eigenlib/Eigen/src/Core/PermutationMatrix.h | 28 - eigenlib/Eigen/src/Core/PlainObjectBase.h | 28 +- eigenlib/Eigen/src/Core/Product.h | 10 +- eigenlib/Eigen/src/Core/ProductEvaluators.h | 65 +- eigenlib/Eigen/src/Core/Redux.h | 2 +- eigenlib/Eigen/src/Core/Ref.h | 7 +- eigenlib/Eigen/src/Core/SelfAdjointView.h | 6 +- eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h | 12 +- eigenlib/Eigen/src/Core/Solve.h | 4 +- eigenlib/Eigen/src/Core/SolveTriangular.h | 9 +- eigenlib/Eigen/src/Core/StableNorm.h | 5 +- eigenlib/Eigen/src/Core/Transpose.h | 2 + eigenlib/Eigen/src/Core/Transpositions.h | 41 +- eigenlib/Eigen/src/Core/TriangularMatrix.h | 8 +- eigenlib/Eigen/src/Core/arch/AVX/Complex.h | 36 +- eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h | 24 +- .../src/Core/arch/AVX512/MathFunctions.h | 95 ++- .../Eigen/src/Core/arch/AVX512/PacketMath.h | 731 +++++++++--------- .../Eigen/src/Core/arch/AltiVec/Complex.h | 37 +- .../Eigen/src/Core/arch/AltiVec/PacketMath.h | 58 +- eigenlib/Eigen/src/Core/arch/CUDA/Half.h | 220 ++++-- .../Eigen/src/Core/arch/CUDA/PacketMath.h | 2 +- .../Eigen/src/Core/arch/CUDA/PacketMathHalf.h | 9 +- .../Eigen/src/Core/arch/Default/ConjHelper.h | 29 + eigenlib/Eigen/src/Core/arch/NEON/Complex.h | 12 +- .../Eigen/src/Core/arch/NEON/PacketMath.h | 98 ++- eigenlib/Eigen/src/Core/arch/SSE/Complex.h | 40 +- eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h | 24 +- .../Eigen/src/Core/arch/SSE/TypeCasting.h | 28 +- .../Eigen/src/Core/arch/ZVector/Complex.h | 3 + .../Eigen/src/Core/arch/ZVector/PacketMath.h | 2 +- .../src/Core/functors/AssignmentFunctors.h | 2 +- .../Eigen/src/Core/functors/BinaryFunctors.h | 25 +- .../Eigen/src/Core/functors/NullaryFunctors.h | 15 +- .../Eigen/src/Core/functors/StlFunctors.h | 4 + .../Eigen/src/Core/functors/UnaryFunctors.h | 2 +- .../Core/products/GeneralBlockPanelKernel.h | 22 +- .../src/Core/products/GeneralMatrixMatrix.h | 45 +- .../products/GeneralMatrixMatrixTriangular.h | 79 +- .../GeneralMatrixMatrixTriangular_BLAS.h | 20 +- .../Core/products/GeneralMatrixMatrix_BLAS.h | 25 +- .../src/Core/products/GeneralMatrixVector.h | 8 +- .../Core/products/GeneralMatrixVector_BLAS.h | 19 +- .../Eigen/src/Core/products/Parallelizer.h | 18 +- .../Core/products/SelfadjointMatrixMatrix.h | 54 +- .../products/SelfadjointMatrixMatrix_BLAS.h | 72 +- .../Core/products/SelfadjointMatrixVector.h | 14 +- .../products/SelfadjointMatrixVector_BLAS.h | 9 +- .../src/Core/products/SelfadjointProduct.h | 4 +- .../Core/products/TriangularMatrixMatrix.h | 89 ++- .../products/TriangularMatrixMatrix_BLAS.h | 65 +- .../Core/products/TriangularMatrixVector.h | 22 +- .../products/TriangularMatrixVector_BLAS.h | 46 +- .../Core/products/TriangularSolverMatrix.h | 62 +- .../products/TriangularSolverMatrix_BLAS.h | 52 +- eigenlib/Eigen/src/Core/util/BlasUtil.h | 115 ++- .../src/Core/util/DisableStupidWarnings.h | 27 +- .../Eigen/src/Core/util/ForwardDeclarations.h | 6 +- eigenlib/Eigen/src/Core/util/MKL_support.h | 10 +- eigenlib/Eigen/src/Core/util/Macros.h | 79 +- eigenlib/Eigen/src/Core/util/Memory.h | 78 +- eigenlib/Eigen/src/Core/util/Meta.h | 76 ++ .../src/Core/util/ReenableStupidWarnings.h | 8 +- eigenlib/Eigen/src/Core/util/StaticAssert.h | 120 +-- eigenlib/Eigen/src/Core/util/XprHelper.h | 19 +- .../src/Eigenvalues/ComplexEigenSolver.h | 6 +- eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h | 9 +- .../src/Eigenvalues/GeneralizedEigenSolver.h | 5 +- .../src/Eigenvalues/MatrixBaseEigenvalues.h | 2 - eigenlib/Eigen/src/Eigenvalues/RealSchur.h | 31 +- .../src/Eigenvalues/SelfAdjointEigenSolver.h | 10 +- .../SelfAdjointEigenSolver_LAPACKE.h | 23 +- eigenlib/Eigen/src/Geometry/AngleAxis.h | 2 +- eigenlib/Eigen/src/Geometry/Quaternion.h | 61 +- eigenlib/Eigen/src/Geometry/Scaling.h | 2 +- eigenlib/Eigen/src/Geometry/Transform.h | 4 +- eigenlib/Eigen/src/Geometry/Translation.h | 6 - eigenlib/Eigen/src/Geometry/Umeyama.h | 2 +- .../Eigen/src/Geometry/arch/Geometry_SSE.h | 60 +- .../Eigen/src/Householder/BlockHouseholder.h | 3 +- .../BasicPreconditioners.h | 27 +- .../ConjugateGradient.h | 5 +- eigenlib/Eigen/src/Jacobi/Jacobi.h | 261 ++++--- eigenlib/Eigen/src/LU/InverseImpl.h | 2 +- eigenlib/Eigen/src/LU/PartialPivLU.h | 5 +- eigenlib/Eigen/src/LU/arch/Inverse_SSE.h | 4 +- .../Eigen/src/OrderingMethods/Eigen_Colamd.h | 2 +- .../Eigen/src/PaStiXSupport/PaStiXSupport.h | 8 +- .../Eigen/src/PardisoSupport/PardisoSupport.h | 3 +- eigenlib/Eigen/src/QR/ColPivHouseholderQR.h | 12 +- eigenlib/Eigen/src/SVD/BDCSVD.h | 171 ++-- eigenlib/Eigen/src/SVD/JacobiSVD.h | 12 +- eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h | 5 +- eigenlib/Eigen/src/SVD/SVDBase.h | 4 +- .../Eigen/src/SVD/UpperBidiagonalization.h | 4 +- .../src/SparseCholesky/SimplicialCholesky.h | 2 +- .../SparseCholesky/SimplicialCholesky_impl.h | 2 +- eigenlib/Eigen/src/SparseCore/AmbiVector.h | 15 +- .../ConservativeSparseSparseProduct.h | 67 +- eigenlib/Eigen/src/SparseCore/SparseAssign.h | 5 +- .../src/SparseCore/SparseCompressedBase.h | 38 +- .../src/SparseCore/SparseCwiseBinaryOp.h | 10 + .../Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 2 + .../src/SparseCore/SparseDiagonalProduct.h | 4 + eigenlib/Eigen/src/SparseCore/SparseMatrix.h | 17 +- .../src/SparseCore/SparseSelfAdjointView.h | 15 +- .../SparseSparseProductWithPruning.h | 22 +- eigenlib/Eigen/src/SparseCore/SparseView.h | 1 + eigenlib/Eigen/src/SparseLU/SparseLU.h | 6 +- eigenlib/Eigen/src/SparseQR/SparseQR.h | 26 +- eigenlib/Eigen/src/StlSupport/StdDeque.h | 6 +- eigenlib/Eigen/src/StlSupport/details.h | 14 +- .../Eigen/src/SuperLUSupport/SuperLUSupport.h | 4 +- .../Eigen/src/UmfPackSupport/UmfPackSupport.h | 101 ++- .../Eigen/src/plugins/ArrayCwiseBinaryOps.h | 2 +- eigenlib/howto.txt | 3 +- 155 files changed, 2860 insertions(+), 1893 deletions(-) create mode 100644 eigenlib/Eigen/src/Core/arch/Default/ConjHelper.h mode change 100755 => 100644 eigenlib/Eigen/src/Geometry/Scaling.h diff --git a/eigenlib/Eigen/Cholesky b/eigenlib/Eigen/Cholesky index 369d1f5e..1332b540 100644 --- a/eigenlib/Eigen/Cholesky +++ b/eigenlib/Eigen/Cholesky @@ -9,6 +9,7 @@ #define EIGEN_CHOLESKY_MODULE_H #include "Core" +#include "Jacobi" #include "src/Core/util/DisableStupidWarnings.h" @@ -31,7 +32,11 @@ #include "src/Cholesky/LLT.h" #include "src/Cholesky/LDLT.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/Cholesky/LLT_LAPACKE.h" #endif diff --git a/eigenlib/Eigen/Core b/eigenlib/Eigen/Core index 82558155..ac7c5b30 100644 --- a/eigenlib/Eigen/Core +++ b/eigenlib/Eigen/Core @@ -14,6 +14,22 @@ // first thing Eigen does: stop the compiler from committing suicide #include "src/Core/util/DisableStupidWarnings.h" +#if defined(__CUDACC__) && !defined(EIGEN_NO_CUDA) + #define EIGEN_CUDACC __CUDACC__ +#endif + +#if defined(__CUDA_ARCH__) && !defined(EIGEN_NO_CUDA) + #define EIGEN_CUDA_ARCH __CUDA_ARCH__ +#endif + +#if defined(__CUDACC_VER_MAJOR__) && (__CUDACC_VER_MAJOR__ >= 9) +#define EIGEN_CUDACC_VER ((__CUDACC_VER_MAJOR__ * 10000) + (__CUDACC_VER_MINOR__ * 100)) +#elif defined(__CUDACC_VER__) +#define EIGEN_CUDACC_VER __CUDACC_VER__ +#else +#define EIGEN_CUDACC_VER 0 +#endif + // Handle NVCC/CUDA/SYCL #if defined(__CUDACC__) || defined(__SYCL_DEVICE_ONLY__) // Do not try asserts on CUDA and SYCL! @@ -37,9 +53,9 @@ #endif #define EIGEN_DEVICE_FUNC __host__ __device__ - // We need math_functions.hpp to ensure that that EIGEN_USING_STD_MATH macro + // We need cuda_runtime.h to ensure that that EIGEN_USING_STD_MATH macro // works properly on the device side - #include + #include #else #define EIGEN_DEVICE_FUNC #endif @@ -155,6 +171,9 @@ #ifdef __AVX512DQ__ #define EIGEN_VECTORIZE_AVX512DQ #endif + #ifdef __AVX512ER__ + #define EIGEN_VECTORIZE_AVX512ER + #endif #endif // include files @@ -229,7 +248,7 @@ #if defined __CUDACC__ #define EIGEN_VECTORIZE_CUDA #include - #if defined __CUDACC_VER__ && __CUDACC_VER__ >= 70500 + #if EIGEN_CUDACC_VER >= 70500 #define EIGEN_HAS_CUDA_FP16 #endif #endif @@ -260,7 +279,10 @@ #include #include #include -#include +#include +#ifndef EIGEN_NO_IO + #include +#endif #include #include #include @@ -321,12 +343,16 @@ inline static const char *SimdInstructionSetsInUse(void) { #error Eigen2-support is only available up to version 3.2. Please go to "http://eigen.tuxfamily.org/index.php?title=Eigen2" for further information #endif +namespace Eigen { + // we use size_t frequently and we'll never remember to prepend it with std:: everytime just to // ensure QNX/QCC support using std::size_t; // gcc 4.6.0 wants std:: for ptrdiff_t using std::ptrdiff_t; +} + /** \defgroup Core_Module Core module * This is the main module of Eigen providing dense matrix and vector support * (both fixed and dynamic size) with all the features corresponding to a BLAS library @@ -348,10 +374,13 @@ using std::ptrdiff_t; #include "src/Core/MathFunctions.h" #include "src/Core/GenericPacketMath.h" #include "src/Core/MathFunctionsImpl.h" +#include "src/Core/arch/Default/ConjHelper.h" #if defined EIGEN_VECTORIZE_AVX512 #include "src/Core/arch/SSE/PacketMath.h" + #include "src/Core/arch/SSE/MathFunctions.h" #include "src/Core/arch/AVX/PacketMath.h" + #include "src/Core/arch/AVX/MathFunctions.h" #include "src/Core/arch/AVX512/PacketMath.h" #include "src/Core/arch/AVX512/MathFunctions.h" #elif defined EIGEN_VECTORIZE_AVX @@ -363,6 +392,7 @@ using std::ptrdiff_t; #include "src/Core/arch/AVX/MathFunctions.h" #include "src/Core/arch/AVX/Complex.h" #include "src/Core/arch/AVX/TypeCasting.h" + #include "src/Core/arch/SSE/TypeCasting.h" #elif defined EIGEN_VECTORIZE_SSE #include "src/Core/arch/SSE/PacketMath.h" #include "src/Core/arch/SSE/MathFunctions.h" @@ -405,6 +435,7 @@ using std::ptrdiff_t; // on CUDA devices #include "src/Core/arch/CUDA/Complex.h" +#include "src/Core/IO.h" #include "src/Core/DenseCoeffsBase.h" #include "src/Core/DenseBase.h" #include "src/Core/MatrixBase.h" @@ -452,7 +483,6 @@ using std::ptrdiff_t; #include "src/Core/Redux.h" #include "src/Core/Visitor.h" #include "src/Core/Fuzzy.h" -#include "src/Core/IO.h" #include "src/Core/Swap.h" #include "src/Core/CommaInitializer.h" #include "src/Core/GeneralProduct.h" diff --git a/eigenlib/Eigen/Eigenvalues b/eigenlib/Eigen/Eigenvalues index 009e529e..7d6ac787 100644 --- a/eigenlib/Eigen/Eigenvalues +++ b/eigenlib/Eigen/Eigenvalues @@ -10,14 +10,14 @@ #include "Core" -#include "src/Core/util/DisableStupidWarnings.h" - #include "Cholesky" #include "Jacobi" #include "Householder" #include "LU" #include "Geometry" +#include "src/Core/util/DisableStupidWarnings.h" + /** \defgroup Eigenvalues_Module Eigenvalues module * * @@ -45,7 +45,11 @@ #include "src/Eigenvalues/GeneralizedEigenSolver.h" #include "src/Eigenvalues/MatrixBaseEigenvalues.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/Eigenvalues/RealSchur_LAPACKE.h" #include "src/Eigenvalues/ComplexSchur_LAPACKE.h" #include "src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h" diff --git a/eigenlib/Eigen/Geometry b/eigenlib/Eigen/Geometry index 716d5295..da88c03b 100644 --- a/eigenlib/Eigen/Geometry +++ b/eigenlib/Eigen/Geometry @@ -10,12 +10,12 @@ #include "Core" -#include "src/Core/util/DisableStupidWarnings.h" - #include "SVD" #include "LU" #include +#include "src/Core/util/DisableStupidWarnings.h" + /** \defgroup Geometry_Module Geometry module * * This module provides support for: diff --git a/eigenlib/Eigen/LU b/eigenlib/Eigen/LU index 6f6c5562..6418a86e 100644 --- a/eigenlib/Eigen/LU +++ b/eigenlib/Eigen/LU @@ -28,7 +28,11 @@ #include "src/LU/FullPivLU.h" #include "src/LU/PartialPivLU.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/LU/PartialPivLU_LAPACKE.h" #endif #include "src/LU/Determinant.h" diff --git a/eigenlib/Eigen/QR b/eigenlib/Eigen/QR index 80838e3b..1be1863a 100644 --- a/eigenlib/Eigen/QR +++ b/eigenlib/Eigen/QR @@ -10,12 +10,12 @@ #include "Core" -#include "src/Core/util/DisableStupidWarnings.h" - #include "Cholesky" #include "Jacobi" #include "Householder" +#include "src/Core/util/DisableStupidWarnings.h" + /** \defgroup QR_Module QR module * * @@ -36,7 +36,11 @@ #include "src/QR/ColPivHouseholderQR.h" #include "src/QR/CompleteOrthogonalDecomposition.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/QR/HouseholderQR_LAPACKE.h" #include "src/QR/ColPivHouseholderQR_LAPACKE.h" #endif diff --git a/eigenlib/Eigen/QtAlignedMalloc b/eigenlib/Eigen/QtAlignedMalloc index 4044d5ac..4f07df02 100644 --- a/eigenlib/Eigen/QtAlignedMalloc +++ b/eigenlib/Eigen/QtAlignedMalloc @@ -14,7 +14,7 @@ #include "src/Core/util/DisableStupidWarnings.h" -void *qMalloc(size_t size) +void *qMalloc(std::size_t size) { return Eigen::internal::aligned_malloc(size); } @@ -24,10 +24,10 @@ void qFree(void *ptr) Eigen::internal::aligned_free(ptr); } -void *qRealloc(void *ptr, size_t size) +void *qRealloc(void *ptr, std::size_t size) { void* newPtr = Eigen::internal::aligned_malloc(size); - memcpy(newPtr, ptr, size); + std::memcpy(newPtr, ptr, size); Eigen::internal::aligned_free(ptr); return newPtr; } diff --git a/eigenlib/Eigen/SVD b/eigenlib/Eigen/SVD index 86143c23..5d0e75f7 100644 --- a/eigenlib/Eigen/SVD +++ b/eigenlib/Eigen/SVD @@ -37,7 +37,11 @@ #include "src/SVD/JacobiSVD.h" #include "src/SVD/BDCSVD.h" #if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT) +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/SVD/JacobiSVD_LAPACKE.h" #endif diff --git a/eigenlib/Eigen/Sparse b/eigenlib/Eigen/Sparse index a2ef7a66..136e681a 100644 --- a/eigenlib/Eigen/Sparse +++ b/eigenlib/Eigen/Sparse @@ -25,7 +25,9 @@ #include "SparseCore" #include "OrderingMethods" +#ifndef EIGEN_MPL2_ONLY #include "SparseCholesky" +#endif #include "SparseLU" #include "SparseQR" #include "IterativeLinearSolvers" diff --git a/eigenlib/Eigen/SparseQR b/eigenlib/Eigen/SparseQR index a6f3b7f7..f5fc5fa7 100644 --- a/eigenlib/Eigen/SparseQR +++ b/eigenlib/Eigen/SparseQR @@ -28,7 +28,6 @@ * */ -#include "OrderingMethods" #include "src/SparseCore/SparseColEtree.h" #include "src/SparseQR/SparseQR.h" diff --git a/eigenlib/Eigen/StdDeque b/eigenlib/Eigen/StdDeque index be3a7f82..bc68397b 100644 --- a/eigenlib/Eigen/StdDeque +++ b/eigenlib/Eigen/StdDeque @@ -14,7 +14,7 @@ #include "Core" #include -#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */ +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ #define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...) diff --git a/eigenlib/Eigen/StdList b/eigenlib/Eigen/StdList index 07ba1297..4c6262c0 100644 --- a/eigenlib/Eigen/StdList +++ b/eigenlib/Eigen/StdList @@ -13,7 +13,7 @@ #include "Core" #include -#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */ +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ #define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...) diff --git a/eigenlib/Eigen/StdVector b/eigenlib/Eigen/StdVector index fdfc3776..0c4697ad 100644 --- a/eigenlib/Eigen/StdVector +++ b/eigenlib/Eigen/StdVector @@ -14,7 +14,7 @@ #include "Core" #include -#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */ +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ #define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...) diff --git a/eigenlib/Eigen/src/Cholesky/LDLT.h b/eigenlib/Eigen/src/Cholesky/LDLT.h index fcee7b2e..15ccf24f 100644 --- a/eigenlib/Eigen/src/Cholesky/LDLT.h +++ b/eigenlib/Eigen/src/Cholesky/LDLT.h @@ -248,7 +248,7 @@ template class LDLT /** \brief Reports whether previous computation was successful. * * \returns \c Success if computation was succesful, - * \c NumericalIssue if the matrix.appears to be negative. + * \c NumericalIssue if the factorization failed because of a zero pivot. */ ComputationInfo info() const { @@ -305,7 +305,8 @@ template<> struct ldlt_inplace if (size <= 1) { transpositions.setIdentity(); - if (numext::real(mat.coeff(0,0)) > static_cast(0) ) sign = PositiveSemiDef; + if(size==0) sign = ZeroSign; + else if (numext::real(mat.coeff(0,0)) > static_cast(0) ) sign = PositiveSemiDef; else if (numext::real(mat.coeff(0,0)) < static_cast(0)) sign = NegativeSemiDef; else sign = ZeroSign; return true; @@ -376,6 +377,8 @@ template<> struct ldlt_inplace if((rs>0) && pivot_is_valid) A21 /= realAkk; + else if(rs>0) + ret = ret && (A21.array()==Scalar(0)).all(); if(found_zero_pivot && pivot_is_valid) ret = false; // factorization failed else if(!pivot_is_valid) found_zero_pivot = true; @@ -568,13 +571,14 @@ void LDLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) cons // more precisely, use pseudo-inverse of D (see bug 241) using std::abs; const typename Diagonal::RealReturnType vecD(vectorD()); - // In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon - // as motivated by LAPACK's xGELSS: + // In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min()) + // and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS: // RealScalar tolerance = numext::maxi(vecD.array().abs().maxCoeff() * NumTraits::epsilon(),RealScalar(1) / NumTraits::highest()); // However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest // diagonal element is not well justified and leads to numerical issues in some cases. // Moreover, Lapack's xSYTRS routines use 0 for the tolerance. - RealScalar tolerance = RealScalar(1) / NumTraits::highest(); + // Using numeric_limits::min() gives us more robustness to denormals. + RealScalar tolerance = (std::numeric_limits::min)(); for (Index i = 0; i < vecD.size(); ++i) { diff --git a/eigenlib/Eigen/src/Cholesky/LLT.h b/eigenlib/Eigen/src/Cholesky/LLT.h index 87ca8d42..e1624d21 100644 --- a/eigenlib/Eigen/src/Cholesky/LLT.h +++ b/eigenlib/Eigen/src/Cholesky/LLT.h @@ -24,7 +24,7 @@ template struct LLT_Traits; * * \tparam _MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition * \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper. - * The other triangular part won't be read. + * The other triangular part won't be read. * * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite * matrix A such that A = LL^* = U^*U, where L is lower triangular. @@ -41,14 +41,18 @@ template struct LLT_Traits; * Example: \include LLT_example.cpp * Output: \verbinclude LLT_example.out * + * \b Performance: for best performance, it is recommended to use a column-major storage format + * with the Lower triangular part (the default), or, equivalently, a row-major storage format + * with the Upper triangular part. Otherwise, you might get a 20% slowdown for the full factorization + * step, and rank-updates can be up to 3 times slower. + * * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. * + * Note that during the decomposition, only the lower (or upper, as defined by _UpLo) triangular part of A is considered. + * Therefore, the strict lower part does not have to store correct values. + * * \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT */ - /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH) - * Note that during the decomposition, only the upper triangular part of A is considered. Therefore, - * the strict lower part does not have to store correct values. - */ template class LLT { public: @@ -146,7 +150,7 @@ template class LLT } template - void solveInPlace(MatrixBase &bAndX) const; + void solveInPlace(const MatrixBase &bAndX) const; template LLT& compute(const EigenBase& matrix); @@ -177,7 +181,7 @@ template class LLT /** \brief Reports whether previous computation was successful. * * \returns \c Success if computation was succesful, - * \c NumericalIssue if the matrix.appears to be negative. + * \c NumericalIssue if the matrix.appears not to be positive definite. */ ComputationInfo info() const { @@ -425,7 +429,8 @@ LLT& LLT::compute(const EigenBase eigen_assert(a.rows()==a.cols()); const Index size = a.rows(); m_matrix.resize(size, size); - m_matrix = a.derived(); + if (!internal::is_same_dense(m_matrix, a.derived())) + m_matrix = a.derived(); // Compute matrix L1 norm = max abs column sum. m_l1_norm = RealScalar(0); @@ -485,11 +490,14 @@ void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const * * This version avoids a copy when the right hand side matrix b is not needed anymore. * + * \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here. + * This function will const_cast it, so constness isn't honored here. + * * \sa LLT::solve(), MatrixBase::llt() */ template template -void LLT::solveInPlace(MatrixBase &bAndX) const +void LLT::solveInPlace(const MatrixBase &bAndX) const { eigen_assert(m_isInitialized && "LLT is not initialized."); eigen_assert(m_matrix.rows()==bAndX.rows()); diff --git a/eigenlib/Eigen/src/Core/Array.h b/eigenlib/Eigen/src/Core/Array.h index 0d34269f..16770fc7 100644 --- a/eigenlib/Eigen/src/Core/Array.h +++ b/eigenlib/Eigen/src/Core/Array.h @@ -153,8 +153,6 @@ class Array : Base(std::move(other)) { Base::_check_template_params(); - if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic) - Base::_set_noalias(other); } EIGEN_DEVICE_FUNC Array& operator=(Array&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable::value) @@ -231,10 +229,16 @@ class Array : Base(other) { } + private: + struct PrivateType {}; + public: + /** \sa MatrixBase::operator=(const EigenBase&) */ template EIGEN_DEVICE_FUNC - EIGEN_STRONG_INLINE Array(const EigenBase &other) + EIGEN_STRONG_INLINE Array(const EigenBase &other, + typename internal::enable_if::value, + PrivateType>::type = PrivateType()) : Base(other.derived()) { } diff --git a/eigenlib/Eigen/src/Core/ArrayBase.h b/eigenlib/Eigen/src/Core/ArrayBase.h index f0232f65..33f644e2 100644 --- a/eigenlib/Eigen/src/Core/ArrayBase.h +++ b/eigenlib/Eigen/src/Core/ArrayBase.h @@ -153,8 +153,8 @@ template class ArrayBase // inline void evalTo(Dest& dst) const { dst = matrix(); } protected: - EIGEN_DEVICE_FUNC - ArrayBase() : Base() {} + EIGEN_DEFAULT_COPY_CONSTRUCTOR(ArrayBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(ArrayBase) private: explicit ArrayBase(Index); @@ -175,7 +175,7 @@ template class ArrayBase */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator-=(const ArrayBase &other) { call_assignment(derived(), other.derived(), internal::sub_assign_op()); @@ -188,7 +188,7 @@ ArrayBase::operator-=(const ArrayBase &other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator+=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::add_assign_op()); @@ -201,7 +201,7 @@ ArrayBase::operator+=(const ArrayBase& other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator*=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::mul_assign_op()); @@ -214,7 +214,7 @@ ArrayBase::operator*=(const ArrayBase& other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator/=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::div_assign_op()); diff --git a/eigenlib/Eigen/src/Core/ArrayWrapper.h b/eigenlib/Eigen/src/Core/ArrayWrapper.h index a04521a1..688aadd6 100644 --- a/eigenlib/Eigen/src/Core/ArrayWrapper.h +++ b/eigenlib/Eigen/src/Core/ArrayWrapper.h @@ -32,7 +32,8 @@ struct traits > // Let's remove NestByRefBit enum { Flags0 = traits::type >::Flags, - Flags = Flags0 & ~NestByRefBit + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag }; }; } @@ -129,7 +130,8 @@ struct traits > // Let's remove NestByRefBit enum { Flags0 = traits::type >::Flags, - Flags = Flags0 & ~NestByRefBit + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag }; }; } diff --git a/eigenlib/Eigen/src/Core/AssignEvaluator.h b/eigenlib/Eigen/src/Core/AssignEvaluator.h index 14400d24..dbe435d8 100644 --- a/eigenlib/Eigen/src/Core/AssignEvaluator.h +++ b/eigenlib/Eigen/src/Core/AssignEvaluator.h @@ -39,7 +39,7 @@ public: enum { DstAlignment = DstEvaluator::Alignment, SrcAlignment = SrcEvaluator::Alignment, - DstHasDirectAccess = DstFlags & DirectAccessBit, + DstHasDirectAccess = (DstFlags & DirectAccessBit) == DirectAccessBit, JointAlignment = EIGEN_PLAIN_ENUM_MIN(DstAlignment,SrcAlignment) }; @@ -83,7 +83,7 @@ private: && int(OuterStride)!=Dynamic && int(OuterStride)%int(InnerPacketSize)==0 && (EIGEN_UNALIGNED_VECTORIZE || int(JointAlignment)>=int(InnerRequiredAlignment)), MayLinearize = bool(StorageOrdersAgree) && (int(DstFlags) & int(SrcFlags) & LinearAccessBit), - MayLinearVectorize = bool(MightVectorize) && MayLinearize && DstHasDirectAccess + MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize) && bool(DstHasDirectAccess) && (EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)) || MaxSizeAtCompileTime == Dynamic), /* If the destination isn't aligned, we have to do runtime checks and we don't unroll, so it's only good for large enough sizes. */ @@ -515,7 +515,7 @@ struct dense_assignment_loop template struct dense_assignment_loop { - EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel) + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel) { typedef typename Kernel::Scalar Scalar; typedef typename Kernel::PacketType PacketType; @@ -563,7 +563,7 @@ struct dense_assignment_loop template struct dense_assignment_loop { - EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel) + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel) { typedef typename Kernel::DstEvaluatorType::XprType DstXprType; typedef typename Kernel::PacketType PacketType; @@ -701,6 +701,26 @@ protected: * Part 5 : Entry point for dense rectangular assignment ***************************************************************************/ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const Functor &/*func*/) +{ + EIGEN_ONLY_USED_FOR_DEBUG(dst); + EIGEN_ONLY_USED_FOR_DEBUG(src); + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const internal::assign_op &/*func*/) +{ + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if(((dst.rows()!=dstRows) || (dst.cols()!=dstCols))) + dst.resize(dstRows, dstCols); + eigen_assert(dst.rows() == dstRows && dst.cols() == dstCols); +} + template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, const Functor &func) { @@ -711,10 +731,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType // NOTE To properly handle A = (A*A.transpose())/s with A rectangular, // we need to resize the destination after the source evaluator has been created. - Index dstRows = src.rows(); - Index dstCols = src.cols(); - if((dst.rows()!=dstRows) || (dst.cols()!=dstCols)) - dst.resize(dstRows, dstCols); + resize_if_allowed(dst, src, func); DstEvaluatorType dstEvaluator(dst); diff --git a/eigenlib/Eigen/src/Core/Assign_MKL.h b/eigenlib/Eigen/src/Core/Assign_MKL.h index 6c2ab926..6866095b 100755 --- a/eigenlib/Eigen/src/Core/Assign_MKL.h +++ b/eigenlib/Eigen/src/Core/Assign_MKL.h @@ -84,7 +84,8 @@ class vml_assign_traits struct Assignment, SrcXprNested>, assign_op, \ Dense2Dense, typename enable_if::EnableVml>::type> { \ typedef CwiseUnaryOp, SrcXprNested> SrcXprType; \ - static void run(DstXprType &dst, const SrcXprType &src, const assign_op &/*func*/) { \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ if(vml_assign_traits::Traversal==LinearTraversal) { \ VMLOP(dst.size(), (const VMLTYPE*)src.nestedExpression().data(), \ @@ -144,7 +145,8 @@ EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil, _) Dense2Dense, typename enable_if::EnableVml>::type> { \ typedef CwiseBinaryOp, SrcXprNested, \ const CwiseNullaryOp,Plain> > SrcXprType; \ - static void run(DstXprType &dst, const SrcXprType &src, const assign_op &/*func*/) { \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ VMLTYPE exponent = reinterpret_cast(src.rhs().functor().m_other); \ if(vml_assign_traits::Traversal==LinearTraversal) \ diff --git a/eigenlib/Eigen/src/Core/ConditionEstimator.h b/eigenlib/Eigen/src/Core/ConditionEstimator.h index aa7efdc7..51a2e5f1 100644 --- a/eigenlib/Eigen/src/Core/ConditionEstimator.h +++ b/eigenlib/Eigen/src/Core/ConditionEstimator.h @@ -160,7 +160,7 @@ rcond_estimate_helper(typename Decomposition::RealScalar matrix_norm, const Deco { typedef typename Decomposition::RealScalar RealScalar; eigen_assert(dec.rows() == dec.cols()); - if (dec.rows() == 0) return RealScalar(1); + if (dec.rows() == 0) return NumTraits::infinity(); if (matrix_norm == RealScalar(0)) return RealScalar(0); if (dec.rows() == 1) return RealScalar(1); const RealScalar inverse_matrix_norm = rcond_invmatrix_L1_norm_estimate(dec); diff --git a/eigenlib/Eigen/src/Core/CoreEvaluators.h b/eigenlib/Eigen/src/Core/CoreEvaluators.h index 1d14af65..910889ef 100644 --- a/eigenlib/Eigen/src/Core/CoreEvaluators.h +++ b/eigenlib/Eigen/src/Core/CoreEvaluators.h @@ -977,7 +977,7 @@ struct evaluator > OuterStrideAtCompileTime = HasSameStorageOrderAsArgType ? int(outer_stride_at_compile_time::ret) : int(inner_stride_at_compile_time::ret), - MaskPacketAccessBit = (InnerStrideAtCompileTime == 1) ? PacketAccessBit : 0, + MaskPacketAccessBit = (InnerStrideAtCompileTime == 1 || HasSameStorageOrderAsArgType) ? PacketAccessBit : 0, FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (evaluator::Flags&LinearAccessBit))) ? LinearAccessBit : 0, FlagsRowMajorBit = XprType::Flags&RowMajorBit, @@ -987,7 +987,9 @@ struct evaluator > Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit, PacketAlignment = unpacket_traits::alignment, - Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0, + Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) + && (OuterStrideAtCompileTime!=0) + && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0, Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator::Alignment, Alignment0) }; typedef block_evaluator block_evaluator_type; @@ -1018,14 +1020,16 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& block) : m_argImpl(block.nestedExpression()), m_startRow(block.startRow()), - m_startCol(block.startCol()) + m_startCol(block.startCol()), + m_linear_offset(InnerPanel?(XprType::IsRowMajor ? block.startRow()*block.cols() : block.startCol()*block.rows()):0) { } typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; enum { - RowsAtCompileTime = XprType::RowsAtCompileTime + RowsAtCompileTime = XprType::RowsAtCompileTime, + ForwardLinearAccess = InnerPanel && bool(evaluator::Flags&LinearAccessBit) }; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE @@ -1037,7 +1041,10 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { - return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.coeff(m_linear_offset.value() + index); + else + return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE @@ -1049,7 +1056,10 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { - return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.coeffRef(m_linear_offset.value() + index); + else + return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template @@ -1063,8 +1073,11 @@ struct unary_evaluator, IndexBa EIGEN_STRONG_INLINE PacketType packet(Index index) const { - return packet(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.template packet(m_linear_offset.value() + index); + else + return packet(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); } template @@ -1078,15 +1091,19 @@ struct unary_evaluator, IndexBa EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { - return writePacket(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0, - x); + if (ForwardLinearAccess) + return m_argImpl.template writePacket(m_linear_offset.value() + index, x); + else + return writePacket(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0, + x); } protected: evaluator m_argImpl; const variable_if_dynamic m_startRow; const variable_if_dynamic m_startCol; + const variable_if_dynamic m_linear_offset; }; // TODO: This evaluator does not actually use the child evaluator; @@ -1556,9 +1573,7 @@ struct evaluator > { } typedef typename XprType::Scalar Scalar; - // FIXME having to check whether ArgType is sparse here i not very nice. - typedef typename internal::conditional::value, - typename XprType::CoeffReturnType,Scalar>::type CoeffReturnType; + typedef typename XprType::CoeffReturnType CoeffReturnType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index) const diff --git a/eigenlib/Eigen/src/Core/CwiseNullaryOp.h b/eigenlib/Eigen/src/Core/CwiseNullaryOp.h index dd498f75..ddd607e3 100644 --- a/eigenlib/Eigen/src/Core/CwiseNullaryOp.h +++ b/eigenlib/Eigen/src/Core/CwiseNullaryOp.h @@ -105,7 +105,7 @@ class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp template -EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> DenseBase::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func) { return CwiseNullaryOp(rows, cols, func); @@ -150,7 +150,7 @@ DenseBase::NullaryExpr(Index size, const CustomNullaryOp& func) */ template template -EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> DenseBase::NullaryExpr(const CustomNullaryOp& func) { return CwiseNullaryOp(RowsAtCompileTime, ColsAtCompileTime, func); @@ -192,7 +192,7 @@ DenseBase::Constant(Index rows, Index cols, const Scalar& value) * \sa class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Constant(Index size, const Scalar& value) { return DenseBase::NullaryExpr(size, internal::scalar_constant_op(value)); @@ -208,7 +208,7 @@ DenseBase::Constant(Index size, const Scalar& value) * \sa class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Constant(const Scalar& value) { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) @@ -220,7 +220,7 @@ DenseBase::Constant(const Scalar& value) * \sa LinSpaced(Index,Scalar,Scalar), setLinSpaced(Index,const Scalar&,const Scalar&) */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -232,7 +232,7 @@ DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const * \sa LinSpaced(Scalar,Scalar) */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -264,7 +264,7 @@ DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig * \sa setLinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -276,7 +276,7 @@ DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) * Special version for fixed size types which does not require the size parameter. */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -286,7 +286,7 @@ DenseBase::LinSpaced(const Scalar& low, const Scalar& high) /** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */ template -bool DenseBase::isApproxToConstant +EIGEN_DEVICE_FUNC bool DenseBase::isApproxToConstant (const Scalar& val, const RealScalar& prec) const { typename internal::nested_eval::type self(derived()); @@ -301,7 +301,7 @@ bool DenseBase::isApproxToConstant * * \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ template -bool DenseBase::isConstant +EIGEN_DEVICE_FUNC bool DenseBase::isConstant (const Scalar& val, const RealScalar& prec) const { return isApproxToConstant(val, prec); @@ -312,7 +312,7 @@ bool DenseBase::isConstant * \sa setConstant(), Constant(), class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) { setConstant(val); } @@ -322,7 +322,7 @@ EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) * \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) { return derived() = Constant(rows(), cols(), val); } @@ -337,7 +337,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index size, const Scalar& val) { resize(size); @@ -356,7 +356,7 @@ PlainObjectBase::setConstant(Index size, const Scalar& val) * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& val) { resize(rows, cols); @@ -380,7 +380,7 @@ PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& val) * \sa LinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op(low,high,newSize)); @@ -400,7 +400,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, con * \sa LinSpaced(Index,const Scalar&,const Scalar&), setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return setLinSpaced(size(), low, high); @@ -423,7 +423,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, * \sa Zero(), Zero(Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero(Index rows, Index cols) { return Constant(rows, cols, Scalar(0)); @@ -446,7 +446,7 @@ DenseBase::Zero(Index rows, Index cols) * \sa Zero(), Zero(Index,Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero(Index size) { return Constant(size, Scalar(0)); @@ -463,7 +463,7 @@ DenseBase::Zero(Index size) * \sa Zero(Index), Zero(Index,Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero() { return Constant(Scalar(0)); @@ -478,7 +478,7 @@ DenseBase::Zero() * \sa class CwiseNullaryOp, Zero() */ template -bool DenseBase::isZero(const RealScalar& prec) const +EIGEN_DEVICE_FUNC bool DenseBase::isZero(const RealScalar& prec) const { typename internal::nested_eval::type self(derived()); for(Index j = 0; j < cols(); ++j) @@ -496,7 +496,7 @@ bool DenseBase::isZero(const RealScalar& prec) const * \sa class CwiseNullaryOp, Zero() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setZero() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setZero() { return setConstant(Scalar(0)); } @@ -511,7 +511,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setZero() * \sa DenseBase::setZero(), setZero(Index,Index), class CwiseNullaryOp, DenseBase::Zero() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index newSize) { resize(newSize); @@ -529,7 +529,7 @@ PlainObjectBase::setZero(Index newSize) * \sa DenseBase::setZero(), setZero(Index), class CwiseNullaryOp, DenseBase::Zero() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index rows, Index cols) { resize(rows, cols); @@ -553,7 +553,7 @@ PlainObjectBase::setZero(Index rows, Index cols) * \sa Ones(), Ones(Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones(Index rows, Index cols) { return Constant(rows, cols, Scalar(1)); @@ -576,7 +576,7 @@ DenseBase::Ones(Index rows, Index cols) * \sa Ones(), Ones(Index,Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones(Index newSize) { return Constant(newSize, Scalar(1)); @@ -593,7 +593,7 @@ DenseBase::Ones(Index newSize) * \sa Ones(Index), Ones(Index,Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones() { return Constant(Scalar(1)); @@ -608,7 +608,7 @@ DenseBase::Ones() * \sa class CwiseNullaryOp, Ones() */ template -bool DenseBase::isOnes +EIGEN_DEVICE_FUNC bool DenseBase::isOnes (const RealScalar& prec) const { return isApproxToConstant(Scalar(1), prec); @@ -622,7 +622,7 @@ bool DenseBase::isOnes * \sa class CwiseNullaryOp, Ones() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() { return setConstant(Scalar(1)); } @@ -637,7 +637,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() * \sa MatrixBase::setOnes(), setOnes(Index,Index), class CwiseNullaryOp, MatrixBase::Ones() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index newSize) { resize(newSize); @@ -655,7 +655,7 @@ PlainObjectBase::setOnes(Index newSize) * \sa MatrixBase::setOnes(), setOnes(Index), class CwiseNullaryOp, MatrixBase::Ones() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index rows, Index cols) { resize(rows, cols); @@ -679,7 +679,7 @@ PlainObjectBase::setOnes(Index rows, Index cols) * \sa Identity(), setIdentity(), isIdentity() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType MatrixBase::Identity(Index rows, Index cols) { return DenseBase::NullaryExpr(rows, cols, internal::scalar_identity_op()); @@ -696,7 +696,7 @@ MatrixBase::Identity(Index rows, Index cols) * \sa Identity(Index,Index), setIdentity(), isIdentity() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType MatrixBase::Identity() { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) @@ -771,7 +771,7 @@ struct setIdentity_impl * \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), isIdentity() */ template -EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() { return internal::setIdentity_impl::run(derived()); } @@ -787,7 +787,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() * \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity() */ template -EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index cols) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index cols) { derived().resize(rows, cols); return setIdentity(); @@ -800,7 +800,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index * \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index newSize, Index i) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index newSize, Index i) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return BasisReturnType(SquareMatrixType::Identity(newSize,newSize), i); @@ -815,7 +815,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index i) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index i) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return BasisReturnType(SquareMatrixType::Identity(),i); @@ -828,7 +828,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitX() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitX() { return Derived::Unit(0); } /** \returns an expression of the Y axis unit vector (0,1{,0}^*) @@ -838,7 +838,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitY() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitY() { return Derived::Unit(1); } /** \returns an expression of the Z axis unit vector (0,0,1{,0}^*) @@ -848,7 +848,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitZ() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitZ() { return Derived::Unit(2); } /** \returns an expression of the W axis unit vector (0,0,0,1) @@ -858,7 +858,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() { return Derived::Unit(3); } } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/CwiseUnaryView.h b/eigenlib/Eigen/src/Core/CwiseUnaryView.h index 27103305..5a30fa8d 100644 --- a/eigenlib/Eigen/src/Core/CwiseUnaryView.h +++ b/eigenlib/Eigen/src/Core/CwiseUnaryView.h @@ -121,6 +121,8 @@ class CwiseUnaryViewImpl { return derived().nestedExpression().outerStride() * sizeof(typename internal::traits::Scalar) / sizeof(Scalar); } + protected: + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(CwiseUnaryViewImpl) }; } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/DenseBase.h b/eigenlib/Eigen/src/Core/DenseBase.h index bd74e8a1..c55a6823 100644 --- a/eigenlib/Eigen/src/Core/DenseBase.h +++ b/eigenlib/Eigen/src/Core/DenseBase.h @@ -40,7 +40,7 @@ static inline void check_DenseIndex_is_signed() { */ template class DenseBase #ifndef EIGEN_PARSED_BY_DOXYGEN - : public DenseCoeffsBase + : public DenseCoeffsBase::value> #else : public DenseCoeffsBase #endif // not EIGEN_PARSED_BY_DOXYGEN @@ -71,7 +71,7 @@ template class DenseBase typedef Scalar value_type; typedef typename NumTraits::Real RealScalar; - typedef DenseCoeffsBase Base; + typedef DenseCoeffsBase::value> Base; using Base::derived; using Base::const_cast_derived; @@ -296,7 +296,7 @@ template class DenseBase EIGEN_DEVICE_FUNC Derived& operator=(const ReturnByValue& func); - /** \ínternal + /** \internal * Copies \a other into *this without evaluating other. \returns a reference to *this. * \deprecated */ template @@ -463,7 +463,17 @@ template class DenseBase EIGEN_DEVICE_FUNC void visit(Visitor& func) const; - inline const WithFormat format(const IOFormat& fmt) const; + /** \returns a WithFormat proxy object allowing to print a matrix the with given + * format \a fmt. + * + * See class IOFormat for some examples. + * + * \sa class IOFormat, class WithFormat + */ + inline const WithFormat format(const IOFormat& fmt) const + { + return WithFormat(derived(), fmt); + } /** \returns the unique coefficient of a 1x1 expression */ EIGEN_DEVICE_FUNC @@ -474,9 +484,9 @@ template class DenseBase return derived().coeff(0,0); } - bool all() const; - bool any() const; - Index count() const; + EIGEN_DEVICE_FUNC bool all() const; + EIGEN_DEVICE_FUNC bool any() const; + EIGEN_DEVICE_FUNC Index count() const; typedef VectorwiseOp RowwiseReturnType; typedef const VectorwiseOp ConstRowwiseReturnType; @@ -577,11 +587,12 @@ template class DenseBase } protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(DenseBase) /** Default constructor. Do nothing. */ EIGEN_DEVICE_FUNC DenseBase() { /* Just checks for self-consistency of the flags. - * Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down + * Only do it when debugging Eigen, as this borders on paranoia and could slow compilation down */ #ifdef EIGEN_INTERNAL_DEBUGGING EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, int(IsRowMajor)) diff --git a/eigenlib/Eigen/src/Core/DenseStorage.h b/eigenlib/Eigen/src/Core/DenseStorage.h index 82201d96..7d6d4e66 100644 --- a/eigenlib/Eigen/src/Core/DenseStorage.h +++ b/eigenlib/Eigen/src/Core/DenseStorage.h @@ -13,9 +13,9 @@ #define EIGEN_MATRIXSTORAGE_H #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN - #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN; + #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) X; EIGEN_DENSE_STORAGE_CTOR_PLUGIN; #else - #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) #endif namespace Eigen { @@ -184,12 +184,16 @@ template class DenseSt { internal::plain_array m_data; public: - EIGEN_DEVICE_FUNC DenseStorage() {} + EIGEN_DEVICE_FUNC DenseStorage() { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + } EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(internal::constructor_without_unaligned_array_assert()) {} EIGEN_DEVICE_FUNC - DenseStorage(const DenseStorage& other) : m_data(other.m_data) {} + DenseStorage(const DenseStorage& other) : m_data(other.m_data) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + } EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other) { @@ -197,7 +201,7 @@ template class DenseSt return *this; } EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows==_Rows && cols==_Cols); EIGEN_UNUSED_VARIABLE(size); EIGEN_UNUSED_VARIABLE(rows); @@ -343,7 +347,7 @@ template class DenseStorage(size)), m_rows(rows), m_cols(cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows>=0 && cols >=0); } EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) @@ -351,6 +355,7 @@ template class DenseStorage class DenseStorage(m_data, m_rows*m_cols); - if (size) + if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative m_data = internal::conditional_aligned_new_auto(size); else m_data = 0; - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) } m_rows = rows; m_cols = cols; @@ -422,7 +427,7 @@ template class DenseStorage(size)), m_cols(cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows==_Rows && cols >=0); EIGEN_UNUSED_VARIABLE(rows); } @@ -430,6 +435,7 @@ template class DenseStorage(_Rows*other.m_cols)) , m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_cols*_Rows) internal::smart_copy(other.m_data, other.m_data+_Rows*m_cols, m_data); } EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other) @@ -473,11 +479,11 @@ template class DenseStorage(m_data, _Rows*m_cols); - if (size) + if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative m_data = internal::conditional_aligned_new_auto(size); else m_data = 0; - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) } m_cols = cols; } @@ -495,7 +501,7 @@ template class DenseStorage(size)), m_rows(rows) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows>=0 && cols == _Cols); EIGEN_UNUSED_VARIABLE(cols); } @@ -503,6 +509,7 @@ template class DenseStorage(other.m_rows*_Cols)) , m_rows(other.m_rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_rows*_Cols) internal::smart_copy(other.m_data, other.m_data+other.m_rows*_Cols, m_data); } EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other) @@ -546,11 +553,11 @@ template class DenseStorage(m_data, _Cols*m_rows); - if (size) + if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative m_data = internal::conditional_aligned_new_auto(size); else m_data = 0; - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) } m_rows = rows; } diff --git a/eigenlib/Eigen/src/Core/Diagonal.h b/eigenlib/Eigen/src/Core/Diagonal.h index bfea0584..afcaf357 100644 --- a/eigenlib/Eigen/src/Core/Diagonal.h +++ b/eigenlib/Eigen/src/Core/Diagonal.h @@ -21,7 +21,7 @@ namespace Eigen { * \param MatrixType the type of the object in which we are taking a sub/main/super diagonal * \param DiagIndex the index of the sub/super diagonal. The default is 0 and it means the main diagonal. * A positive value means a superdiagonal, a negative value means a subdiagonal. - * You can also use Dynamic so the index can be set at runtime. + * You can also use DynamicIndex so the index can be set at runtime. * * The matrix is not required to be square. * @@ -70,7 +70,10 @@ template class Diagonal EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal) EIGEN_DEVICE_FUNC - explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) {} + explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) + { + eigen_assert( a_index <= m_matrix.cols() && -a_index <= m_matrix.rows() ); + } EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal) diff --git a/eigenlib/Eigen/src/Core/Dot.h b/eigenlib/Eigen/src/Core/Dot.h index 06ef18b8..1fe7a84a 100644 --- a/eigenlib/Eigen/src/Core/Dot.h +++ b/eigenlib/Eigen/src/Core/Dot.h @@ -31,7 +31,8 @@ struct dot_nocheck typedef scalar_conj_product_op::Scalar,typename traits::Scalar> conj_prod; typedef typename conj_prod::result_type ResScalar; EIGEN_DEVICE_FUNC - static inline ResScalar run(const MatrixBase& a, const MatrixBase& b) + EIGEN_STRONG_INLINE + static ResScalar run(const MatrixBase& a, const MatrixBase& b) { return a.template binaryExpr(b).sum(); } @@ -43,7 +44,8 @@ struct dot_nocheck typedef scalar_conj_product_op::Scalar,typename traits::Scalar> conj_prod; typedef typename conj_prod::result_type ResScalar; EIGEN_DEVICE_FUNC - static inline ResScalar run(const MatrixBase& a, const MatrixBase& b) + EIGEN_STRONG_INLINE + static ResScalar run(const MatrixBase& a, const MatrixBase& b) { return a.transpose().template binaryExpr(b).sum(); } @@ -65,6 +67,7 @@ struct dot_nocheck template template EIGEN_DEVICE_FUNC +EIGEN_STRONG_INLINE typename ScalarBinaryOpTraits::Scalar,typename internal::traits::Scalar>::ReturnType MatrixBase::dot(const MatrixBase& other) const { @@ -102,7 +105,7 @@ EIGEN_STRONG_INLINE typename NumTraits::Scala * \sa lpNorm(), dot(), squaredNorm() */ template -inline typename NumTraits::Scalar>::Real MatrixBase::norm() const +EIGEN_STRONG_INLINE typename NumTraits::Scalar>::Real MatrixBase::norm() const { return numext::sqrt(squaredNorm()); } @@ -117,7 +120,7 @@ inline typename NumTraits::Scalar>::Real Matr * \sa norm(), normalize() */ template -inline const typename MatrixBase::PlainObject +EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject MatrixBase::normalized() const { typedef typename internal::nested_eval::type _Nested; @@ -139,7 +142,7 @@ MatrixBase::normalized() const * \sa norm(), normalized() */ template -inline void MatrixBase::normalize() +EIGEN_STRONG_INLINE void MatrixBase::normalize() { RealScalar z = squaredNorm(); // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU @@ -160,7 +163,7 @@ inline void MatrixBase::normalize() * \sa stableNorm(), stableNormalize(), normalized() */ template -inline const typename MatrixBase::PlainObject +EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject MatrixBase::stableNormalized() const { typedef typename internal::nested_eval::type _Nested; @@ -185,7 +188,7 @@ MatrixBase::stableNormalized() const * \sa stableNorm(), stableNormalized(), normalize() */ template -inline void MatrixBase::stableNormalize() +EIGEN_STRONG_INLINE void MatrixBase::stableNormalize() { RealScalar w = cwiseAbs().maxCoeff(); RealScalar z = (derived()/w).squaredNorm(); diff --git a/eigenlib/Eigen/src/Core/EigenBase.h b/eigenlib/Eigen/src/Core/EigenBase.h index f76995af..b195506a 100644 --- a/eigenlib/Eigen/src/Core/EigenBase.h +++ b/eigenlib/Eigen/src/Core/EigenBase.h @@ -14,6 +14,7 @@ namespace Eigen { /** \class EigenBase + * \ingroup Core_Module * * Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T). * @@ -128,6 +129,7 @@ template struct EigenBase */ template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator=(const EigenBase &other) { call_assignment(derived(), other.derived()); @@ -136,6 +138,7 @@ Derived& DenseBase::operator=(const EigenBase &other) template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator+=(const EigenBase &other) { call_assignment(derived(), other.derived(), internal::add_assign_op()); @@ -144,6 +147,7 @@ Derived& DenseBase::operator+=(const EigenBase &other) template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator-=(const EigenBase &other) { call_assignment(derived(), other.derived(), internal::sub_assign_op()); diff --git a/eigenlib/Eigen/src/Core/GeneralProduct.h b/eigenlib/Eigen/src/Core/GeneralProduct.h index 0f16cd8e..6f0cc80e 100644 --- a/eigenlib/Eigen/src/Core/GeneralProduct.h +++ b/eigenlib/Eigen/src/Core/GeneralProduct.h @@ -24,12 +24,17 @@ template struct product_type_selector; template struct product_size_category { - enum { is_large = MaxSize == Dynamic || - Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD || - (Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD), - value = is_large ? Large - : Size == 1 ? 1 - : Small + enum { + #ifndef EIGEN_CUDA_ARCH + is_large = MaxSize == Dynamic || + Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD || + (Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD), + #else + is_large = 0, + #endif + value = is_large ? Large + : Size == 1 ? 1 + : Small }; }; @@ -379,8 +384,6 @@ template<> struct gemv_dense_selector * * \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*() */ -#ifndef __CUDACC__ - template template inline const Product @@ -412,8 +415,6 @@ MatrixBase::operator*(const MatrixBase &other) const return Product(derived(), other.derived()); } -#endif // __CUDACC__ - /** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. * * The returned product will behave like any other expressions: the coefficients of the product will be diff --git a/eigenlib/Eigen/src/Core/GenericPacketMath.h b/eigenlib/Eigen/src/Core/GenericPacketMath.h index 27033a2d..e5944377 100644 --- a/eigenlib/Eigen/src/Core/GenericPacketMath.h +++ b/eigenlib/Eigen/src/Core/GenericPacketMath.h @@ -230,7 +230,7 @@ pload1(const typename unpacket_traits::type *a) { return pset1( * duplicated to form: {from[0],from[0],from[1],from[1],from[2],from[2],from[3],from[3]} * Currently, this function is only used for scalar * complex products. */ -template EIGEN_DEVICE_FUNC inline Packet +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet ploaddup(const typename unpacket_traits::type* from) { return *from; } /** \internal \returns a packet with elements of \a *from quadrupled. @@ -278,7 +278,7 @@ inline void pbroadcast2(const typename unpacket_traits::type *a, } /** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */ -template inline Packet +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet plset(const typename unpacket_traits::type& a) { return a; } /** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */ @@ -351,10 +351,7 @@ template EIGEN_DEVICE_FUNC inline Packet preverse(const Packet& /** \internal \returns \a a with real and imaginary part flipped (for complex type only) */ template EIGEN_DEVICE_FUNC inline Packet pcplxflip(const Packet& a) { - // FIXME: uncomment the following in case we drop the internal imag and real functions. -// using std::imag; -// using std::real; - return Packet(imag(a),real(a)); + return Packet(a.imag(),a.real()); } /************************** @@ -482,7 +479,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pstoret(Scalar* to, const Packet& fro * by the current computation. */ template -inline Packet ploadt_ro(const typename unpacket_traits::type* from) +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_ro(const typename unpacket_traits::type* from) { return ploadt(from); } @@ -524,10 +521,10 @@ inline void palign(PacketType& first, const PacketType& second) #ifndef __CUDACC__ template<> inline std::complex pmul(const std::complex& a, const std::complex& b) -{ return std::complex(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); } +{ return std::complex(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); } template<> inline std::complex pmul(const std::complex& a, const std::complex& b) -{ return std::complex(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); } +{ return std::complex(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); } #endif diff --git a/eigenlib/Eigen/src/Core/IO.h b/eigenlib/Eigen/src/Core/IO.h index 644228c3..da7fd6cc 100644 --- a/eigenlib/Eigen/src/Core/IO.h +++ b/eigenlib/Eigen/src/Core/IO.h @@ -109,20 +109,6 @@ class WithFormat IOFormat m_format; }; -/** \returns a WithFormat proxy object allowing to print a matrix the with given - * format \a fmt. - * - * See class IOFormat for some examples. - * - * \sa class IOFormat, class WithFormat - */ -template -inline const WithFormat -DenseBase::format(const IOFormat& fmt) const -{ - return WithFormat(derived(), fmt); -} - namespace internal { // NOTE: This helper is kept for backward compatibility with previous code specializing diff --git a/eigenlib/Eigen/src/Core/Map.h b/eigenlib/Eigen/src/Core/Map.h index 06d19670..548bf9a2 100644 --- a/eigenlib/Eigen/src/Core/Map.h +++ b/eigenlib/Eigen/src/Core/Map.h @@ -20,11 +20,17 @@ struct traits > { typedef traits TraitsBase; enum { + PlainObjectTypeInnerSize = ((traits::Flags&RowMajorBit)==RowMajorBit) + ? PlainObjectType::ColsAtCompileTime + : PlainObjectType::RowsAtCompileTime, + InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0 ? int(PlainObjectType::InnerStrideAtCompileTime) : int(StrideType::InnerStrideAtCompileTime), OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0 - ? int(PlainObjectType::OuterStrideAtCompileTime) + ? (InnerStrideAtCompileTime==Dynamic || PlainObjectTypeInnerSize==Dynamic + ? Dynamic + : int(InnerStrideAtCompileTime) * int(PlainObjectTypeInnerSize)) : int(StrideType::OuterStrideAtCompileTime), Alignment = int(MapOptions)&int(AlignedMask), Flags0 = TraitsBase::Flags & (~NestByRefBit), @@ -107,10 +113,11 @@ template class Ma EIGEN_DEVICE_FUNC inline Index outerStride() const { - return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() - : IsVectorAtCompileTime ? this->size() - : int(Flags)&RowMajorBit ? this->cols() - : this->rows(); + return int(StrideType::OuterStrideAtCompileTime) != 0 ? m_stride.outer() + : int(internal::traits::OuterStrideAtCompileTime) != Dynamic ? Index(internal::traits::OuterStrideAtCompileTime) + : IsVectorAtCompileTime ? (this->size() * innerStride()) + : (int(Flags)&RowMajorBit) ? (this->cols() * innerStride()) + : (this->rows() * innerStride()); } /** Constructor in the fixed-size case. diff --git a/eigenlib/Eigen/src/Core/MapBase.h b/eigenlib/Eigen/src/Core/MapBase.h index 020f939a..92c3b281 100644 --- a/eigenlib/Eigen/src/Core/MapBase.h +++ b/eigenlib/Eigen/src/Core/MapBase.h @@ -43,6 +43,7 @@ template class MapBase enum { RowsAtCompileTime = internal::traits::RowsAtCompileTime, ColsAtCompileTime = internal::traits::ColsAtCompileTime, + InnerStrideAtCompileTime = internal::traits::InnerStrideAtCompileTime, SizeAtCompileTime = Base::SizeAtCompileTime }; @@ -181,14 +182,19 @@ template class MapBase #endif protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) template EIGEN_DEVICE_FUNC void checkSanity(typename internal::enable_if<(internal::traits::Alignment>0),void*>::type = 0) const { #if EIGEN_MAX_ALIGN_BYTES>0 + // innerStride() is not set yet when this function is called, so we optimistically assume the lowest plausible value: + const Index minInnerStride = InnerStrideAtCompileTime == Dynamic ? 1 : Index(InnerStrideAtCompileTime); + EIGEN_ONLY_USED_FOR_DEBUG(minInnerStride); eigen_assert(( ((internal::UIntPtr(m_data) % internal::traits::Alignment) == 0) - || (cols() * rows() * innerStride() * sizeof(Scalar)) < internal::traits::Alignment ) && "data is not aligned"); + || (cols() * rows() * minInnerStride * sizeof(Scalar)) < internal::traits::Alignment ) && "data is not aligned"); #endif } @@ -290,6 +296,9 @@ template class MapBase // In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base, // see bugs 821 and 920. using ReadOnlyMapBase::Base::operator=; + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) }; #undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS diff --git a/eigenlib/Eigen/src/Core/MathFunctions.h b/eigenlib/Eigen/src/Core/MathFunctions.h index 8d47fb8a..01736c2a 100644 --- a/eigenlib/Eigen/src/Core/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/MathFunctions.h @@ -287,7 +287,7 @@ struct abs2_impl_default // IsComplex EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { - return real(x)*real(x) + imag(x)*imag(x); + return x.real()*x.real() + x.imag()*x.imag(); } }; @@ -313,14 +313,17 @@ struct abs2_retval ****************************************************************************/ template -struct norm1_default_impl +struct norm1_default_impl; + +template +struct norm1_default_impl { typedef typename NumTraits::Real RealScalar; EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { EIGEN_USING_STD_MATH(abs); - return abs(real(x)) + abs(imag(x)); + return abs(x.real()) + abs(x.imag()); } }; @@ -348,31 +351,7 @@ struct norm1_retval * Implementation of hypot * ****************************************************************************/ -template -struct hypot_impl -{ - typedef typename NumTraits::Real RealScalar; - static inline RealScalar run(const Scalar& x, const Scalar& y) - { - EIGEN_USING_STD_MATH(abs); - EIGEN_USING_STD_MATH(sqrt); - RealScalar _x = abs(x); - RealScalar _y = abs(y); - Scalar p, qp; - if(_x>_y) - { - p = _x; - qp = _y / p; - } - else - { - p = _y; - qp = _x / p; - } - if(p==RealScalar(0)) return RealScalar(0); - return p * sqrt(RealScalar(1) + qp*qp); - } -}; +template struct hypot_impl; template struct hypot_retval @@ -495,7 +474,7 @@ namespace std_fallback { typedef typename NumTraits::Real RealScalar; EIGEN_USING_STD_MATH(log); Scalar x1p = RealScalar(1) + x; - return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); + return numext::equal_strict(x1p, Scalar(1)) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); } } @@ -640,21 +619,28 @@ template struct random_default_impl { static inline Scalar run(const Scalar& x, const Scalar& y) - { - typedef typename conditional::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX; - if(y=x the result converted to an unsigned long is still correct. - std::size_t range = ScalarX(y)-ScalarX(x); - std::size_t offset = 0; - // rejection sampling - std::size_t divisor = 1; - std::size_t multiplier = 1; - if(range::type ScalarU; + // ScalarX is the widest of ScalarU and unsigned int. + // We'll deal only with ScalarX and unsigned int below thus avoiding signed + // types and arithmetic and signed overflows (which are undefined behavior). + typedef typename conditional<(ScalarU(-1) > unsigned(-1)), ScalarU, unsigned>::type ScalarX; + // The following difference doesn't overflow, provided our integer types are two's + // complement and have the same number of padding bits in signed and unsigned variants. + // This is the case in most modern implementations of C++. + ScalarX range = ScalarX(y) - ScalarX(x); + ScalarX offset = 0; + ScalarX divisor = 1; + ScalarX multiplier = 1; + const unsigned rand_max = RAND_MAX; + if (range <= rand_max) divisor = (rand_max + 1) / (range + 1); + else multiplier = 1 + range / (rand_max + 1); + // Rejection sampling. do { - offset = (std::size_t(std::rand()) * multiplier) / divisor; + offset = (unsigned(std::rand()) * multiplier) / divisor; } while (offset > range); return Scalar(ScalarX(x) + offset); } @@ -679,8 +665,8 @@ struct random_default_impl { static inline Scalar run(const Scalar& x, const Scalar& y) { - return Scalar(random(real(x), real(y)), - random(imag(x), imag(y))); + return Scalar(random(x.real(), y.real()), + random(x.imag(), y.imag())); } static inline Scalar run() { @@ -933,6 +919,9 @@ inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); } +EIGEN_DEVICE_FUNC +inline bool abs2(bool x) { return x; } + template EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) @@ -1030,7 +1019,8 @@ inline int log2(int x) /** \returns the square root of \a x. * - * It is essentially equivalent to \code using std::sqrt; return sqrt(x); \endcode, + * It is essentially equivalent to + * \code using std::sqrt; return sqrt(x); \endcode * but slightly faster for float/double and some compilers (e.g., gcc), thanks to * specializations when SSE is enabled. * @@ -1061,11 +1051,24 @@ double log(const double &x) { return ::log(x); } template EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE -typename NumTraits::Real abs(const T &x) { +typename internal::enable_if::IsSigned || NumTraits::IsComplex,typename NumTraits::Real>::type +abs(const T &x) { EIGEN_USING_STD_MATH(abs); return abs(x); } +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE +typename internal::enable_if::IsSigned || NumTraits::IsComplex),typename NumTraits::Real>::type +abs(const T &x) { + return x; +} + +#if defined(__SYCL_DEVICE_ONLY__) +EIGEN_ALWAYS_INLINE float abs(float x) { return cl::sycl::fabs(x); } +EIGEN_ALWAYS_INLINE double abs(double x) { return cl::sycl::fabs(x); } +#endif // defined(__SYCL_DEVICE_ONLY__) + #ifdef __CUDACC__ template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float abs(const float &x) { return ::fabsf(x); } diff --git a/eigenlib/Eigen/src/Core/MathFunctionsImpl.h b/eigenlib/Eigen/src/Core/MathFunctionsImpl.h index 3c9ef22f..9c1ceb0e 100644 --- a/eigenlib/Eigen/src/Core/MathFunctionsImpl.h +++ b/eigenlib/Eigen/src/Core/MathFunctionsImpl.h @@ -71,6 +71,29 @@ T generic_fast_tanh_float(const T& a_x) return pdiv(p, q); } +template +EIGEN_STRONG_INLINE +RealScalar positive_real_hypot(const RealScalar& x, const RealScalar& y) +{ + EIGEN_USING_STD_MATH(sqrt); + RealScalar p, qp; + p = numext::maxi(x,y); + if(p==RealScalar(0)) return RealScalar(0); + qp = numext::mini(y,x) / p; + return p * sqrt(RealScalar(1) + qp*qp); +} + +template +struct hypot_impl +{ + typedef typename NumTraits::Real RealScalar; + static inline RealScalar run(const Scalar& x, const Scalar& y) + { + EIGEN_USING_STD_MATH(abs); + return positive_real_hypot(abs(x), abs(y)); + } +}; + } // end namespace internal } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/Matrix.h b/eigenlib/Eigen/src/Core/Matrix.h index 90c336d8..7f4a7af9 100644 --- a/eigenlib/Eigen/src/Core/Matrix.h +++ b/eigenlib/Eigen/src/Core/Matrix.h @@ -274,8 +274,6 @@ class Matrix : Base(std::move(other)) { Base::_check_template_params(); - if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic) - Base::_set_noalias(other); } EIGEN_DEVICE_FUNC Matrix& operator=(Matrix&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable::value) diff --git a/eigenlib/Eigen/src/Core/MatrixBase.h b/eigenlib/Eigen/src/Core/MatrixBase.h index f7cf04cd..f8bcc8c6 100644 --- a/eigenlib/Eigen/src/Core/MatrixBase.h +++ b/eigenlib/Eigen/src/Core/MatrixBase.h @@ -160,20 +160,11 @@ template class MatrixBase EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const MatrixBase& other); -#ifdef __CUDACC__ template EIGEN_DEVICE_FUNC - const Product - operator*(const MatrixBase &other) const - { return this->lazyProduct(other); } -#else - - template const Product operator*(const MatrixBase &other) const; -#endif - template EIGEN_DEVICE_FUNC const Product @@ -294,7 +285,7 @@ template class MatrixBase * fuzzy comparison such as isApprox() * \sa isApprox(), operator!= */ template - inline bool operator==(const MatrixBase& other) const + EIGEN_DEVICE_FUNC inline bool operator==(const MatrixBase& other) const { return cwiseEqual(other).all(); } /** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other. @@ -302,7 +293,7 @@ template class MatrixBase * fuzzy comparison such as isApprox() * \sa isApprox(), operator== */ template - inline bool operator!=(const MatrixBase& other) const + EIGEN_DEVICE_FUNC inline bool operator!=(const MatrixBase& other) const { return cwiseNotEqual(other).any(); } NoAlias noalias(); @@ -453,19 +444,28 @@ template class MatrixBase ///////// MatrixFunctions module ///////// typedef typename internal::stem_function::type StemFunction; - const MatrixExponentialReturnValue exp() const; +#define EIGEN_MATRIX_FUNCTION(ReturnType, Name, Description) \ + /** \returns an expression of the matrix Description of \c *this. \brief This function requires the unsupported MatrixFunctions module. To compute the coefficient-wise Description use ArrayBase::##Name . */ \ + const ReturnType Name() const; +#define EIGEN_MATRIX_FUNCTION_1(ReturnType, Name, Description, Argument) \ + /** \returns an expression of the matrix Description of \c *this. \brief This function requires the unsupported MatrixFunctions module. To compute the coefficient-wise Description use ArrayBase::##Name . */ \ + const ReturnType Name(Argument) const; + + EIGEN_MATRIX_FUNCTION(MatrixExponentialReturnValue, exp, exponential) + /** \brief Helper function for the unsupported MatrixFunctions module.*/ const MatrixFunctionReturnValue matrixFunction(StemFunction f) const; - const MatrixFunctionReturnValue cosh() const; - const MatrixFunctionReturnValue sinh() const; - const MatrixFunctionReturnValue cos() const; - const MatrixFunctionReturnValue sin() const; - const MatrixSquareRootReturnValue sqrt() const; - const MatrixLogarithmReturnValue log() const; - const MatrixPowerReturnValue pow(const RealScalar& p) const; - const MatrixComplexPowerReturnValue pow(const std::complex& p) const; + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cosh, hyperbolic cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sinh, hyperbolic sine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cos, cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sin, sine) + EIGEN_MATRIX_FUNCTION(MatrixSquareRootReturnValue, sqrt, square root) + EIGEN_MATRIX_FUNCTION(MatrixLogarithmReturnValue, log, logarithm) + EIGEN_MATRIX_FUNCTION_1(MatrixPowerReturnValue, pow, power to \c p, const RealScalar& p) + EIGEN_MATRIX_FUNCTION_1(MatrixComplexPowerReturnValue, pow, power to \c p, const std::complex& p) protected: - EIGEN_DEVICE_FUNC MatrixBase() : Base() {} + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MatrixBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MatrixBase) private: EIGEN_DEVICE_FUNC explicit MatrixBase(int); diff --git a/eigenlib/Eigen/src/Core/NumTraits.h b/eigenlib/Eigen/src/Core/NumTraits.h index dd61195b..daf48987 100644 --- a/eigenlib/Eigen/src/Core/NumTraits.h +++ b/eigenlib/Eigen/src/Core/NumTraits.h @@ -215,6 +215,8 @@ struct NumTraits > static inline RealScalar epsilon() { return NumTraits::epsilon(); } EIGEN_DEVICE_FUNC static inline RealScalar dummy_precision() { return NumTraits::dummy_precision(); } + + static inline int digits10() { return NumTraits::digits10(); } }; template<> struct NumTraits diff --git a/eigenlib/Eigen/src/Core/PermutationMatrix.h b/eigenlib/Eigen/src/Core/PermutationMatrix.h index b1fb455b..47c06ba7 100644 --- a/eigenlib/Eigen/src/Core/PermutationMatrix.h +++ b/eigenlib/Eigen/src/Core/PermutationMatrix.h @@ -87,17 +87,6 @@ class PermutationBase : public EigenBase return derived(); } - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** This is a special case of the templated operator=. Its purpose is to - * prevent a default operator= from hiding the templated operator=. - */ - Derived& operator=(const PermutationBase& other) - { - indices() = other.indices(); - return derived(); - } - #endif - /** \returns the number of rows */ inline Index rows() const { return Index(indices().size()); } @@ -333,12 +322,6 @@ class PermutationMatrix : public PermutationBase& other) : m_indices(other.indices()) {} - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** Standard copy constructor. Defined only to prevent a default copy constructor - * from hiding the other templated constructor */ - inline PermutationMatrix(const PermutationMatrix& other) : m_indices(other.indices()) {} - #endif - /** Generic constructor from expression of the indices. The indices * array has the meaning that the permutations sends each integer i to indices[i]. * @@ -373,17 +356,6 @@ class PermutationMatrix : public PermutationBase struct check_rows_cols_for_overflow { { // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 // we assume Index is signed - Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed + Index max_index = (std::size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed bool error = (rows == 0 || cols == 0) ? false : (rows > max_index / cols); if (error) @@ -577,6 +577,10 @@ class PlainObjectBase : public internal::dense_xpr_base::type * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned * \a data pointers. * + * Here is an example using strides: + * \include Matrix_Map_stride.cpp + * Output: \verbinclude Matrix_Map_stride.out + * * \see class Map */ //@{ @@ -733,8 +737,10 @@ class PlainObjectBase : public internal::dense_xpr_base::type EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if::type* = 0) { - EIGEN_STATIC_ASSERT(bool(NumTraits::IsInteger) && - bool(NumTraits::IsInteger), + const bool t0_is_integer_alike = internal::is_valid_index_type::value; + const bool t1_is_integer_alike = internal::is_valid_index_type::value; + EIGEN_STATIC_ASSERT(t0_is_integer_alike && + t1_is_integer_alike, FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) resize(rows,cols); } @@ -769,9 +775,9 @@ class PlainObjectBase : public internal::dense_xpr_base::type && ((!internal::is_same::XprKind,ArrayXpr>::value || Base::SizeAtCompileTime==Dynamic)),T>::type* = 0) { // NOTE MSVC 2008 complains if we directly put bool(NumTraits::IsInteger) as the EIGEN_STATIC_ASSERT argument. - const bool is_integer = NumTraits::IsInteger; - EIGEN_UNUSED_VARIABLE(is_integer); - EIGEN_STATIC_ASSERT(is_integer, + const bool is_integer_alike = internal::is_valid_index_type::value; + EIGEN_UNUSED_VARIABLE(is_integer_alike); + EIGEN_STATIC_ASSERT(is_integer_alike, FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) resize(size); } @@ -812,6 +818,13 @@ class PlainObjectBase : public internal::dense_xpr_base::type this->_set_noalias(other); } + // Initialize an arbitrary matrix from an object convertible to the Derived type. + template + EIGEN_DEVICE_FUNC + EIGEN_STRONG_INLINE void _init1(const Derived& other){ + this->_set_noalias(other); + } + // Initialize an arbitrary matrix from a generic Eigen expression template EIGEN_DEVICE_FUNC @@ -834,7 +847,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type this->derived() = r; } - // For fixed -size arrays: + // For fixed-size Array template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const Scalar& val0, @@ -846,6 +859,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type Base::setConstant(val0); } + // For fixed-size Array template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const Index& val0, diff --git a/eigenlib/Eigen/src/Core/Product.h b/eigenlib/Eigen/src/Core/Product.h index ae0c94b3..676c4802 100644 --- a/eigenlib/Eigen/src/Core/Product.h +++ b/eigenlib/Eigen/src/Core/Product.h @@ -97,8 +97,8 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option, && "if you wanted a coeff-wise or a dot product use the respective explicit functions"); } - EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); } - EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); } EIGEN_DEVICE_FUNC const LhsNestedCleaned& lhs() const { return m_lhs; } EIGEN_DEVICE_FUNC const RhsNestedCleaned& rhs() const { return m_rhs; } @@ -127,7 +127,7 @@ public: using Base::derived; typedef typename Base::Scalar Scalar; - operator const Scalar() const + EIGEN_STRONG_INLINE operator const Scalar() const { return internal::evaluator(derived()).coeff(0,0); } @@ -162,7 +162,7 @@ class ProductImpl public: - EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const { EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) ); @@ -170,7 +170,7 @@ class ProductImpl return internal::evaluator(derived()).coeff(row,col); } - EIGEN_DEVICE_FUNC Scalar coeff(Index i) const + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index i) const { EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) ); diff --git a/eigenlib/Eigen/src/Core/ProductEvaluators.h b/eigenlib/Eigen/src/Core/ProductEvaluators.h index 583b7f59..bce1310c 100644 --- a/eigenlib/Eigen/src/Core/ProductEvaluators.h +++ b/eigenlib/Eigen/src/Core/ProductEvaluators.h @@ -32,7 +32,7 @@ struct evaluator > typedef Product XprType; typedef product_evaluator Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr) {} }; // Catch "scalar * ( A * B )" and transform it to "(A*scalar) * B" @@ -55,7 +55,7 @@ struct evaluator, const Product > XprType; typedef evaluator > Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr.lhs().functor().m_other * xpr.rhs().lhs() * xpr.rhs().rhs()) {} }; @@ -68,7 +68,7 @@ struct evaluator, DiagIndex> > typedef Diagonal, DiagIndex> XprType; typedef evaluator, DiagIndex> > Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(Diagonal, DiagIndex>( Product(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()), xpr.index() )) @@ -207,6 +207,12 @@ struct evaluator_assume_aliasing +struct evaluator_assume_aliasing::Scalar>, const OtherXpr, + const Product >, DenseShape > { + static const bool value = true; +}; + template struct assignment_from_xpr_op_product { @@ -240,19 +246,19 @@ template struct generic_product_impl { template - static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum(); } template - static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) += (lhs.transpose().cwiseProduct(rhs)).sum(); } template - static void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) -= (lhs.transpose().cwiseProduct(rhs)).sum(); } }; @@ -306,25 +312,25 @@ struct generic_product_impl }; template - static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, set(), is_row_major()); } template - static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, add(), is_row_major()); } template - static inline void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, sub(), is_row_major()); } template - static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) + static EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { internal::outer_product_selector_run(dst, lhs, rhs, adds(alpha), is_row_major()); } @@ -390,7 +396,7 @@ struct generic_product_impl // but easier on the compiler side call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::assign_op()); } - + template static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { @@ -404,6 +410,32 @@ struct generic_product_impl // dst.noalias() -= lhs.lazyProduct(rhs); call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::sub_assign_op()); } + + // Catch "dst {,+,-}= (s*A)*B" and evaluate it lazily by moving out the scalar factor: + // dst {,+,-}= s * (A.lazyProduct(B)) + // This is a huge benefit for heap-allocated matrix types as it save one costly allocation. + // For them, this strategy is also faster than simply by-passing the heap allocation through + // stack allocation. + // For fixed sizes matrices, this is less obvious, it is sometimes x2 faster, but sometimes x3 slower, + // and the behavior depends also a lot on the compiler... so let's be conservative and enable them for dynamic-size only, + // that is when coming from generic_product_impl<...,GemmProduct> in file GeneralMatrixMatrix.h + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + void eval_dynamic(Dst& dst, const CwiseBinaryOp, + const CwiseNullaryOp, Plain1>, Xpr2>& lhs, const Rhs& rhs, const Func &func) + { + call_assignment_no_alias(dst, lhs.lhs().functor().m_other * lhs.rhs().lazyProduct(rhs), func); + } + + // Here, we we always have LhsT==Lhs, but we need to make it a template type to make the above + // overload more specialized. + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + void eval_dynamic(Dst& dst, const LhsT& lhs, const Rhs& rhs, const Func &func) + { + call_assignment_no_alias(dst, lhs.lazyProduct(rhs), func); + } + // template // static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) @@ -779,7 +811,11 @@ public: _Vectorizable = bool(int(MatrixFlags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagFlags)&PacketAccessBit))), _LinearAccessMask = (MatrixType::RowsAtCompileTime==1 || MatrixType::ColsAtCompileTime==1) ? LinearAccessBit : 0, Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixFlags)) | (_Vectorizable ? PacketAccessBit : 0), - Alignment = evaluator::Alignment + Alignment = evaluator::Alignment, + + AsScalarProduct = (DiagonalType::SizeAtCompileTime==1) + || (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::RowsAtCompileTime==1 && ProductOrder==OnTheLeft) + || (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::ColsAtCompileTime==1 && ProductOrder==OnTheRight) }; diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag) @@ -791,7 +827,10 @@ public: EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const { - return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx); + if(AsScalarProduct) + return m_diagImpl.coeff(0) * m_matImpl.coeff(idx); + else + return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx); } protected: diff --git a/eigenlib/Eigen/src/Core/Redux.h b/eigenlib/Eigen/src/Core/Redux.h index b6e8f888..760e9f86 100644 --- a/eigenlib/Eigen/src/Core/Redux.h +++ b/eigenlib/Eigen/src/Core/Redux.h @@ -407,7 +407,7 @@ protected: */ template template -typename internal::traits::Scalar +EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::redux(const Func& func) const { eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix"); diff --git a/eigenlib/Eigen/src/Core/Ref.h b/eigenlib/Eigen/src/Core/Ref.h index bdf24f52..17a1496b 100644 --- a/eigenlib/Eigen/src/Core/Ref.h +++ b/eigenlib/Eigen/src/Core/Ref.h @@ -28,12 +28,13 @@ struct traits > template struct match { enum { + IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime, HasDirectAccess = internal::has_direct_access::ret, - StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), + StorageOrderMatch = IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic) || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime) || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1), - OuterStrideMatch = Derived::IsVectorAtCompileTime + OuterStrideMatch = IsVectorAtCompileTime || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime), // NOTE, this indirection of evaluator::Alignment is needed // to workaround a very strange bug in MSVC related to the instantiation @@ -95,6 +96,8 @@ protected: template EIGEN_DEVICE_FUNC void construct(Expression& expr) { + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(PlainObjectType,Expression); + if(PlainObjectType::RowsAtCompileTime==1) { eigen_assert(expr.rows()==1 || expr.cols()==1); diff --git a/eigenlib/Eigen/src/Core/SelfAdjointView.h b/eigenlib/Eigen/src/Core/SelfAdjointView.h index 504c98f0..b2e51f37 100644 --- a/eigenlib/Eigen/src/Core/SelfAdjointView.h +++ b/eigenlib/Eigen/src/Core/SelfAdjointView.h @@ -71,7 +71,9 @@ template class SelfAdjointView EIGEN_DEVICE_FUNC explicit inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix) - {} + { + EIGEN_STATIC_ASSERT(UpLo==Lower || UpLo==Upper,SELFADJOINTVIEW_ACCEPTS_UPPER_AND_LOWER_MODE_ONLY); + } EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.rows(); } @@ -189,7 +191,7 @@ template class SelfAdjointView TriangularView >::type(tmp2); } - typedef SelfAdjointView ConjugateReturnType; + typedef SelfAdjointView ConjugateReturnType; /** \sa MatrixBase::conjugate() const */ EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const diff --git a/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h b/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h index 719ed72a..7c89c2e2 100644 --- a/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h +++ b/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h @@ -15,33 +15,29 @@ namespace Eigen { // TODO generalize the scalar type of 'other' template -EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::mul_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& ArrayBase::operator+=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase::operator+=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::add_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& ArrayBase::operator-=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase::operator-=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::sub_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::div_assign_op()); return derived(); } diff --git a/eigenlib/Eigen/src/Core/Solve.h b/eigenlib/Eigen/src/Core/Solve.h index 960a5859..a8daea51 100644 --- a/eigenlib/Eigen/src/Core/Solve.h +++ b/eigenlib/Eigen/src/Core/Solve.h @@ -34,12 +34,12 @@ template struct s template struct solve_traits { - typedef Matrix PlainObject; + RhsType::MaxColsAtCompileTime>::type PlainObject; }; template diff --git a/eigenlib/Eigen/src/Core/SolveTriangular.h b/eigenlib/Eigen/src/Core/SolveTriangular.h index 049890b2..fd0acb1a 100644 --- a/eigenlib/Eigen/src/Core/SolveTriangular.h +++ b/eigenlib/Eigen/src/Core/SolveTriangular.h @@ -19,7 +19,7 @@ namespace internal { template struct triangular_solve_vector; -template +template struct triangular_solve_matrix; // small helper struct extracting some traits on the underlying solver operation @@ -98,8 +98,8 @@ struct triangular_solver_selector BlockingType blocking(rhs.rows(), rhs.cols(), size, 1, false); triangular_solve_matrix - ::run(size, othersize, &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.outerStride(), blocking); + (Rhs::Flags&RowMajorBit) ? RowMajor : ColMajor, Rhs::InnerStrideAtCompileTime> + ::run(size, othersize, &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.innerStride(), rhs.outerStride(), blocking); } }; @@ -169,6 +169,9 @@ void TriangularViewImpl::solveInPlace(const MatrixBase::Flags & RowMajorBit) && OtherDerived::IsVectorAtCompileTime && OtherDerived::SizeAtCompileTime!=1}; typedef typename internal::conditional::stableNorm() const typedef typename internal::nested_eval::type DerivedCopy; typedef typename internal::remove_all::type DerivedCopyClean; - DerivedCopy copy(derived()); + const DerivedCopy copy(derived()); enum { CanAlign = ( (int(DerivedCopyClean::Flags)&DirectAccessBit) || (int(internal::evaluator::Alignment)>0) // FIXME Alignment)>0 might not be enough - ) && (blockSize*sizeof(Scalar)*20) // if we cannot allocate on the stack, then let's not bother about this optimization }; typedef typename internal::conditional, internal::evaluator::Alignment>, typename DerivedCopyClean::ConstSegmentReturnType>::type SegmentWrapper; diff --git a/eigenlib/Eigen/src/Core/Transpose.h b/eigenlib/Eigen/src/Core/Transpose.h index 79b767bc..960dc451 100644 --- a/eigenlib/Eigen/src/Core/Transpose.h +++ b/eigenlib/Eigen/src/Core/Transpose.h @@ -146,6 +146,8 @@ template class TransposeImpl { return derived().nestedExpression().coeffRef(index); } + protected: + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TransposeImpl) }; /** \returns an expression of the transpose of *this. diff --git a/eigenlib/Eigen/src/Core/Transpositions.h b/eigenlib/Eigen/src/Core/Transpositions.h index 19c17bb4..7718625e 100644 --- a/eigenlib/Eigen/src/Core/Transpositions.h +++ b/eigenlib/Eigen/src/Core/Transpositions.h @@ -33,17 +33,6 @@ class TranspositionsBase indices() = other.indices(); return derived(); } - - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** This is a special case of the templated operator=. Its purpose is to - * prevent a default operator= from hiding the templated operator=. - */ - Derived& operator=(const TranspositionsBase& other) - { - indices() = other.indices(); - return derived(); - } - #endif /** \returns the number of transpositions */ Index size() const { return indices().size(); } @@ -171,12 +160,6 @@ class Transpositions : public TranspositionsBase& other) : m_indices(other.indices()) {} - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** Standard copy constructor. Defined only to prevent a default copy constructor - * from hiding the other templated constructor */ - inline Transpositions(const Transpositions& other) : m_indices(other.indices()) {} - #endif - /** Generic constructor from expression of the transposition indices. */ template explicit inline Transpositions(const MatrixBase& indices) : m_indices(indices) @@ -189,17 +172,6 @@ class Transpositions : public TranspositionsBase > const Product operator*(const MatrixBase& matrix, const Transpose& trt) { - return Product(matrix.derived(), trt.derived()); + return Product(matrix.derived(), trt); } /** \returns the \a matrix with the inverse transpositions applied to the rows. diff --git a/eigenlib/Eigen/src/Core/TriangularMatrix.h b/eigenlib/Eigen/src/Core/TriangularMatrix.h index 667ef09d..9abb7e31 100644 --- a/eigenlib/Eigen/src/Core/TriangularMatrix.h +++ b/eigenlib/Eigen/src/Core/TriangularMatrix.h @@ -217,9 +217,7 @@ template class TriangularView explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) {} - using Base::operator=; - TriangularView& operator=(const TriangularView &other) - { return Base::operator=(other); } + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView) /** \copydoc EigenBase::rows() */ EIGEN_DEVICE_FUNC @@ -544,6 +542,10 @@ template class TriangularViewImpl<_Mat template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha, bool beta); + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl) + }; /*************************************************************************** diff --git a/eigenlib/Eigen/src/Core/arch/AVX/Complex.h b/eigenlib/Eigen/src/Core/arch/AVX/Complex.h index 99439c8a..7fa61969 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/AVX/Complex.h @@ -204,23 +204,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet8f& x, const Packet4cf& y, const Packet4cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet4cf pmul(const Packet8f& x, const Packet4cf& y) const - { return Packet4cf(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet8f& y, const Packet4cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& x, const Packet8f& y) const - { return Packet4cf(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet4cf,Packet8f) template<> EIGEN_STRONG_INLINE Packet4cf pdiv(const Packet4cf& a, const Packet4cf& b) { @@ -400,23 +384,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet4d& x, const Packet2cd& y, const Packet2cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cd pmul(const Packet4d& x, const Packet2cd& y) const - { return Packet2cd(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet4d& y, const Packet2cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& x, const Packet4d& y) const - { return Packet2cd(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cd,Packet4d) template<> EIGEN_STRONG_INLINE Packet2cd pdiv(const Packet2cd& a, const Packet2cd& b) { diff --git a/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h b/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h index 195d40fb..923a124b 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h @@ -159,11 +159,12 @@ template<> EIGEN_STRONG_INLINE Packet8i pdiv(const Packet8i& /*a*/, co #ifdef __FMA__ template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f& b, const Packet8f& c) { -#if ( EIGEN_COMP_GNUC_STRICT || (EIGEN_COMP_CLANG && (EIGEN_COMP_CLANG<308)) ) - // clang stupidly generates a vfmadd213ps instruction plus some vmovaps on registers, - // and gcc stupidly generates a vfmadd132ps instruction, - // so let's enforce it to generate a vfmadd231ps instruction since the most common use case is to accumulate - // the result of the product. +#if ( (EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC<80) || (EIGEN_COMP_CLANG) ) + // Clang stupidly generates a vfmadd213ps instruction plus some vmovaps on registers, + // and even register spilling with clang>=6.0 (bug 1637). + // Gcc stupidly generates a vfmadd132ps instruction. + // So let's enforce it to generate a vfmadd231ps instruction since the most common use + // case is to accumulate the result of the product. Packet8f res = c; __asm__("vfmadd231ps %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b)); return res; @@ -172,7 +173,7 @@ template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f& #endif } template<> EIGEN_STRONG_INLINE Packet4d pmadd(const Packet4d& a, const Packet4d& b, const Packet4d& c) { -#if ( EIGEN_COMP_GNUC_STRICT || (EIGEN_COMP_CLANG && (EIGEN_COMP_CLANG<308)) ) +#if ( (EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC<80) || (EIGEN_COMP_CLANG) ) // see above Packet4d res = c; __asm__("vfmadd231pd %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b)); @@ -308,9 +309,9 @@ template<> EIGEN_STRONG_INLINE void pstore1(int* to, const int& a) } #ifndef EIGEN_VECTORIZE_AVX512 -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } #endif template<> EIGEN_STRONG_INLINE float pfirst(const Packet8f& a) { @@ -333,9 +334,12 @@ template<> EIGEN_STRONG_INLINE Packet4d preverse(const Packet4d& a) { __m256d tmp = _mm256_shuffle_pd(a,a,5); return _mm256_permute2f128_pd(tmp, tmp, 1); - + #if 0 + // This version is unlikely to be faster as _mm256_shuffle_ps and _mm256_permute_pd + // exhibit the same latency/throughput, but it is here for future reference/benchmarking... __m256d swap_halves = _mm256_permute2f128_pd(a,a,1); return _mm256_permute_pd(swap_halves,5); + #endif } // pabs should be ok diff --git a/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h index 399be0ee..b259c1e1 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h @@ -29,6 +29,7 @@ namespace internal { #define _EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(NAME, X) \ const Packet8d p8d_##NAME = _mm512_castsi512_pd(_mm512_set1_epi64(X)) + // Natural logarithm // Computes log(x) as log(2^e * m) = C*e + log(m), where the constant C =log(2) // and m is in the range [sqrt(1/2),sqrt(2)). In this range, the logarithm can @@ -47,6 +48,7 @@ plog(const Packet16f& _x) { // The smallest non denormalized float number. _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(min_norm_pos, 0x00800000); _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(minus_inf, 0xff800000); + _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(pos_inf, 0x7f800000); _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(nan, 0x7fc00000); // Polynomial coefficients. @@ -64,11 +66,9 @@ plog(const Packet16f& _x) { _EIGEN_DECLARE_CONST_Packet16f(cephes_log_q2, 0.693359375f); // invalid_mask is set to true when x is NaN - __mmask16 invalid_mask = - _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_NGE_UQ); - __mmask16 iszero_mask = - _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_EQ_UQ); - + __mmask16 invalid_mask = _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_NGE_UQ); + __mmask16 iszero_mask = _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_EQ_OQ); + // Truncate input values to the minimum positive normal. x = pmax(x, p16f_min_norm_pos); @@ -88,9 +88,9 @@ plog(const Packet16f& _x) { // x = x + x - 1.0; // } else { x = x - 1.0; } __mmask16 mask = _mm512_cmp_ps_mask(x, p16f_cephes_SQRTHF, _CMP_LT_OQ); - Packet16f tmp = _mm512_mask_blend_ps(mask, x, _mm512_setzero_ps()); + Packet16f tmp = _mm512_mask_blend_ps(mask, _mm512_setzero_ps(), x); x = psub(x, p16f_1); - e = psub(e, _mm512_mask_blend_ps(mask, p16f_1, _mm512_setzero_ps())); + e = psub(e, _mm512_mask_blend_ps(mask, _mm512_setzero_ps(), p16f_1)); x = padd(x, tmp); Packet16f x2 = pmul(x, x); @@ -118,10 +118,18 @@ plog(const Packet16f& _x) { x = padd(x, y); x = padd(x, y2); - // Filter out invalid inputs, i.e. negative arg will be NAN, 0 will be -INF. - return _mm512_mask_blend_ps(iszero_mask, p16f_minus_inf, - _mm512_mask_blend_ps(invalid_mask, p16f_nan, x)); + __mmask16 pos_inf_mask = _mm512_cmp_ps_mask(_x,p16f_pos_inf,_CMP_EQ_OQ); + // Filter out invalid inputs, i.e.: + // - negative arg will be NAN, + // - 0 will be -INF. + // - +INF will be +INF + return _mm512_mask_blend_ps(iszero_mask, + _mm512_mask_blend_ps(invalid_mask, + _mm512_mask_blend_ps(pos_inf_mask,x,p16f_pos_inf), + p16f_nan), + p16f_minus_inf); } + #endif // Exponential function. Works by writing "x = m*log(2) + r" where @@ -257,50 +265,39 @@ pexp(const Packet8d& _x) { template <> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet16f psqrt(const Packet16f& _x) { - _EIGEN_DECLARE_CONST_Packet16f(one_point_five, 1.5f); - _EIGEN_DECLARE_CONST_Packet16f(minus_half, -0.5f); - _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(flt_min, 0x00800000); + Packet16f neg_half = pmul(_x, pset1(-.5f)); + __mmask16 denormal_mask = _mm512_kand( + _mm512_cmp_ps_mask(_x, pset1((std::numeric_limits::min)()), + _CMP_LT_OQ), + _mm512_cmp_ps_mask(_x, _mm512_setzero_ps(), _CMP_GE_OQ)); - Packet16f neg_half = pmul(_x, p16f_minus_half); - - // select only the inverse sqrt of positive normal inputs (denormals are - // flushed to zero and cause infs as well). - __mmask16 non_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_GE_OQ); - Packet16f x = _mm512_mask_blend_ps(non_zero_mask, _mm512_rsqrt14_ps(_x), - _mm512_setzero_ps()); + Packet16f x = _mm512_rsqrt14_ps(_x); // Do a single step of Newton's iteration. - x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five)); + x = pmul(x, pmadd(neg_half, pmul(x, x), pset1(1.5f))); - // Multiply the original _x by it's reciprocal square root to extract the - // square root. - return pmul(_x, x); + // Flush results for denormals to zero. + return _mm512_mask_blend_ps(denormal_mask, pmul(_x,x), _mm512_setzero_ps()); } template <> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8d psqrt(const Packet8d& _x) { - _EIGEN_DECLARE_CONST_Packet8d(one_point_five, 1.5); - _EIGEN_DECLARE_CONST_Packet8d(minus_half, -0.5); - _EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(dbl_min, 0x0010000000000000LL); + Packet8d neg_half = pmul(_x, pset1(-.5)); + __mmask16 denormal_mask = _mm512_kand( + _mm512_cmp_pd_mask(_x, pset1((std::numeric_limits::min)()), + _CMP_LT_OQ), + _mm512_cmp_pd_mask(_x, _mm512_setzero_pd(), _CMP_GE_OQ)); - Packet8d neg_half = pmul(_x, p8d_minus_half); + Packet8d x = _mm512_rsqrt14_pd(_x); - // select only the inverse sqrt of positive normal inputs (denormals are - // flushed to zero and cause infs as well). - __mmask8 non_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_GE_OQ); - Packet8d x = _mm512_mask_blend_pd(non_zero_mask, _mm512_rsqrt14_pd(_x), - _mm512_setzero_pd()); - - // Do a first step of Newton's iteration. - x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); + // Do a single step of Newton's iteration. + x = pmul(x, pmadd(neg_half, pmul(x, x), pset1(1.5))); // Do a second step of Newton's iteration. - x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); + x = pmul(x, pmadd(neg_half, pmul(x, x), pset1(1.5))); - // Multiply the original _x by it's reciprocal square root to extract the - // square root. - return pmul(_x, x); + return _mm512_mask_blend_pd(denormal_mask, pmul(_x,x), _mm512_setzero_pd()); } #else template <> @@ -333,20 +330,18 @@ prsqrt(const Packet16f& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask16 le_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_LT_OQ); - Packet16f x = _mm512_mask_blend_ps(le_zero_mask, _mm512_setzero_ps(), - _mm512_rsqrt14_ps(_x)); + Packet16f x = _mm512_mask_blend_ps(le_zero_mask, _mm512_rsqrt14_ps(_x), _mm512_setzero_ps()); // Fill in NaNs and Infs for the negative/zero entries. __mmask16 neg_mask = _mm512_cmp_ps_mask(_x, _mm512_setzero_ps(), _CMP_LT_OQ); Packet16f infs_and_nans = _mm512_mask_blend_ps( - neg_mask, p16f_nan, - _mm512_mask_blend_ps(le_zero_mask, p16f_inf, _mm512_setzero_ps())); + neg_mask, _mm512_mask_blend_ps(le_zero_mask, _mm512_setzero_ps(), p16f_inf), p16f_nan); // Do a single step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five)); // Insert NaNs and Infs in all the right places. - return _mm512_mask_blend_ps(le_zero_mask, infs_and_nans, x); + return _mm512_mask_blend_ps(le_zero_mask, x, infs_and_nans); } template <> @@ -363,14 +358,12 @@ prsqrt(const Packet8d& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask8 le_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_LT_OQ); - Packet8d x = _mm512_mask_blend_pd(le_zero_mask, _mm512_setzero_pd(), - _mm512_rsqrt14_pd(_x)); + Packet8d x = _mm512_mask_blend_pd(le_zero_mask, _mm512_rsqrt14_pd(_x), _mm512_setzero_pd()); // Fill in NaNs and Infs for the negative/zero entries. __mmask8 neg_mask = _mm512_cmp_pd_mask(_x, _mm512_setzero_pd(), _CMP_LT_OQ); Packet8d infs_and_nans = _mm512_mask_blend_pd( - neg_mask, p8d_nan, - _mm512_mask_blend_pd(le_zero_mask, p8d_inf, _mm512_setzero_pd())); + neg_mask, _mm512_mask_blend_pd(le_zero_mask, _mm512_setzero_pd(), p8d_inf), p8d_nan); // Do a first step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); @@ -379,9 +372,9 @@ prsqrt(const Packet8d& _x) { x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); // Insert NaNs and Infs in all the right places. - return _mm512_mask_blend_pd(le_zero_mask, infs_and_nans, x); + return _mm512_mask_blend_pd(le_zero_mask, x, infs_and_nans); } -#else +#elif defined(EIGEN_VECTORIZE_AVX512ER) template <> EIGEN_STRONG_INLINE Packet16f prsqrt(const Packet16f& x) { return _mm512_rsqrt28_ps(x); diff --git a/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h b/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h index f6500a16..000b7762 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h @@ -19,10 +19,10 @@ namespace internal { #endif #ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS -#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS (2*sizeof(void*)) +#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 32 #endif -#ifdef __FMA__ +#ifdef EIGEN_VECTORIZE_FMA #ifndef EIGEN_HAS_SINGLE_INSTRUCTION_MADD #define EIGEN_HAS_SINGLE_INSTRUCTION_MADD #endif @@ -54,13 +54,14 @@ template<> struct packet_traits : default_packet_traits AlignedOnScalar = 1, size = 16, HasHalfPacket = 1, -#if EIGEN_GNUC_AT_LEAST(5, 3) + HasBlend = 0, +#if EIGEN_GNUC_AT_LEAST(5, 3) || (!EIGEN_COMP_GNUC_STRICT) #ifdef EIGEN_VECTORIZE_AVX512DQ HasLog = 1, #endif HasExp = 1, - HasSqrt = 1, - HasRsqrt = 1, + HasSqrt = EIGEN_FAST_MATH, + HasRsqrt = EIGEN_FAST_MATH, #endif HasDiv = 1 }; @@ -74,8 +75,8 @@ template<> struct packet_traits : default_packet_traits AlignedOnScalar = 1, size = 8, HasHalfPacket = 1, -#if EIGEN_GNUC_AT_LEAST(5, 3) - HasSqrt = 1, +#if EIGEN_GNUC_AT_LEAST(5, 3) || (!EIGEN_COMP_GNUC_STRICT) + HasSqrt = EIGEN_FAST_MATH, HasRsqrt = EIGEN_FAST_MATH, #endif HasDiv = 1 @@ -98,6 +99,7 @@ template <> struct unpacket_traits { typedef float type; typedef Packet8f half; + typedef Packet16i integer_packet; enum { size = 16, alignment=Aligned64 }; }; template <> @@ -132,7 +134,7 @@ EIGEN_STRONG_INLINE Packet16f pload1(const float* from) { } template <> EIGEN_STRONG_INLINE Packet8d pload1(const double* from) { - return _mm512_broadcastsd_pd(_mm_load_pd1(from)); + return _mm512_set1_pd(*from); } template <> @@ -158,6 +160,11 @@ EIGEN_STRONG_INLINE Packet8d padd(const Packet8d& a, const Packet8d& b) { return _mm512_add_pd(a, b); } +template <> +EIGEN_STRONG_INLINE Packet16i padd(const Packet16i& a, + const Packet16i& b) { + return _mm512_add_epi32(a, b); +} template <> EIGEN_STRONG_INLINE Packet16f psub(const Packet16f& a, @@ -169,6 +176,11 @@ EIGEN_STRONG_INLINE Packet8d psub(const Packet8d& a, const Packet8d& b) { return _mm512_sub_pd(a, b); } +template <> +EIGEN_STRONG_INLINE Packet16i psub(const Packet16i& a, + const Packet16i& b) { + return _mm512_sub_epi32(a, b); +} template <> EIGEN_STRONG_INLINE Packet16f pnegate(const Packet16f& a) { @@ -202,6 +214,11 @@ EIGEN_STRONG_INLINE Packet8d pmul(const Packet8d& a, const Packet8d& b) { return _mm512_mul_pd(a, b); } +template <> +EIGEN_STRONG_INLINE Packet16i pmul(const Packet16i& a, + const Packet16i& b) { + return _mm512_mul_epi32(a, b); +} template <> EIGEN_STRONG_INLINE Packet16f pdiv(const Packet16f& a, @@ -214,7 +231,7 @@ EIGEN_STRONG_INLINE Packet8d pdiv(const Packet8d& a, return _mm512_div_pd(a, b); } -#ifdef __FMA__ +#ifdef EIGEN_VECTORIZE_FMA template <> EIGEN_STRONG_INLINE Packet16f pmadd(const Packet16f& a, const Packet16f& b, const Packet16f& c) { @@ -230,23 +247,73 @@ EIGEN_STRONG_INLINE Packet8d pmadd(const Packet8d& a, const Packet8d& b, template <> EIGEN_STRONG_INLINE Packet16f pmin(const Packet16f& a, const Packet16f& b) { - return _mm512_min_ps(a, b); + // Arguments are reversed to match NaN propagation behavior of std::min. + return _mm512_min_ps(b, a); } template <> EIGEN_STRONG_INLINE Packet8d pmin(const Packet8d& a, const Packet8d& b) { - return _mm512_min_pd(a, b); + // Arguments are reversed to match NaN propagation behavior of std::min. + return _mm512_min_pd(b, a); } template <> EIGEN_STRONG_INLINE Packet16f pmax(const Packet16f& a, const Packet16f& b) { - return _mm512_max_ps(a, b); + // Arguments are reversed to match NaN propagation behavior of std::max. + return _mm512_max_ps(b, a); } template <> EIGEN_STRONG_INLINE Packet8d pmax(const Packet8d& a, const Packet8d& b) { - return _mm512_max_pd(a, b); + // Arguments are reversed to match NaN propagation behavior of std::max. + return _mm512_max_pd(b, a); +} + +#ifdef EIGEN_VECTORIZE_AVX512DQ +template EIGEN_STRONG_INLINE Packet8f extract256(Packet16f x) { return _mm512_extractf32x8_ps(x,I_); } +template EIGEN_STRONG_INLINE Packet2d extract128(Packet8d x) { return _mm512_extractf64x2_pd(x,I_); } +EIGEN_STRONG_INLINE Packet16f cat256(Packet8f a, Packet8f b) { return _mm512_insertf32x8(_mm512_castps256_ps512(a),b,1); } +#else +// AVX512F does not define _mm512_extractf32x8_ps to extract _m256 from _m512 +template EIGEN_STRONG_INLINE Packet8f extract256(Packet16f x) { + return _mm256_castsi256_ps(_mm512_extracti64x4_epi64( _mm512_castps_si512(x),I_)); +} + +// AVX512F does not define _mm512_extractf64x2_pd to extract _m128 from _m512 +template EIGEN_STRONG_INLINE Packet2d extract128(Packet8d x) { + return _mm_castsi128_pd(_mm512_extracti32x4_epi32( _mm512_castpd_si512(x),I_)); +} + +EIGEN_STRONG_INLINE Packet16f cat256(Packet8f a, Packet8f b) { + return _mm512_castsi512_ps(_mm512_inserti64x4(_mm512_castsi256_si512(_mm256_castps_si256(a)), + _mm256_castps_si256(b),1)); +} +#endif + +// Helper function for bit packing snippet of low precision comparison. +// It packs the flags from 32x16 to 16x16. +EIGEN_STRONG_INLINE __m256i Pack32To16(Packet16f rf) { + // Split data into small pieces and handle with AVX instructions + // to guarantee internal order of vector. + // Operation: + // dst[15:0] := Saturate16(rf[31:0]) + // dst[31:16] := Saturate16(rf[63:32]) + // ... + // dst[255:240] := Saturate16(rf[255:224]) + __m256i lo = _mm256_castps_si256(extract256<0>(rf)); + __m256i hi = _mm256_castps_si256(extract256<1>(rf)); + __m128i result_lo = _mm_packs_epi32(_mm256_extractf128_si256(lo, 0), + _mm256_extractf128_si256(lo, 1)); + __m128i result_hi = _mm_packs_epi32(_mm256_extractf128_si256(hi, 0), + _mm256_extractf128_si256(hi, 1)); + return _mm256_insertf128_si256(_mm256_castsi128_si256(result_lo), result_hi, 1); +} + +template <> +EIGEN_STRONG_INLINE Packet16i pand(const Packet16i& a, + const Packet16i& b) { + return _mm512_and_si512(a,b); } template <> @@ -255,24 +322,7 @@ EIGEN_STRONG_INLINE Packet16f pand(const Packet16f& a, #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_and_ps(a, b); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_and_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_and_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_and_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_and_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(pand(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } template <> @@ -288,35 +338,21 @@ EIGEN_STRONG_INLINE Packet8d pand(const Packet8d& a, Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_and_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_insertf64x4(res, _mm256_and_pd(lane1_a, lane1_b), 1); #endif } + template <> -EIGEN_STRONG_INLINE Packet16f por(const Packet16f& a, - const Packet16f& b) { +EIGEN_STRONG_INLINE Packet16i por(const Packet16i& a, const Packet16i& b) { + return _mm512_or_si512(a, b); +} + +template <> +EIGEN_STRONG_INLINE Packet16f por(const Packet16f& a, const Packet16f& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_or_ps(a, b); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_or_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_or_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_or_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_or_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(por(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } @@ -326,109 +362,67 @@ EIGEN_STRONG_INLINE Packet8d por(const Packet8d& a, #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_or_pd(a, b); #else - Packet8d res = _mm512_undefined_pd(); - Packet4d lane0_a = _mm512_extractf64x4_pd(a, 0); - Packet4d lane0_b = _mm512_extractf64x4_pd(b, 0); - res = _mm512_insertf64x4(res, _mm256_or_pd(lane0_a, lane0_b), 0); - - Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); - Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_or_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_castsi512_pd(por(_mm512_castpd_si512(a),_mm512_castpd_si512(b))); #endif } template <> -EIGEN_STRONG_INLINE Packet16f pxor(const Packet16f& a, - const Packet16f& b) { +EIGEN_STRONG_INLINE Packet16i pxor(const Packet16i& a, const Packet16i& b) { + return _mm512_xor_si512(a, b); +} + +template <> +EIGEN_STRONG_INLINE Packet16f pxor(const Packet16f& a, const Packet16f& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_xor_ps(a, b); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(pxor(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } + template <> -EIGEN_STRONG_INLINE Packet8d pxor(const Packet8d& a, - const Packet8d& b) { +EIGEN_STRONG_INLINE Packet8d pxor(const Packet8d& a, const Packet8d& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_xor_pd(a, b); #else - Packet8d res = _mm512_undefined_pd(); - Packet4d lane0_a = _mm512_extractf64x4_pd(a, 0); - Packet4d lane0_b = _mm512_extractf64x4_pd(b, 0); - res = _mm512_insertf64x4(res, _mm256_xor_pd(lane0_a, lane0_b), 0); - - Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); - Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_xor_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_castsi512_pd(pxor(_mm512_castpd_si512(a),_mm512_castpd_si512(b))); #endif } template <> -EIGEN_STRONG_INLINE Packet16f pandnot(const Packet16f& a, - const Packet16f& b) { +EIGEN_STRONG_INLINE Packet16i pandnot(const Packet16i& a, const Packet16i& b) { + return _mm512_andnot_si512(b, a); +} + +template <> +EIGEN_STRONG_INLINE Packet16f pandnot(const Packet16f& a, const Packet16f& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ - return _mm512_andnot_ps(a, b); + return _mm512_andnot_ps(b, a); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(pandnot(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } template <> -EIGEN_STRONG_INLINE Packet8d pandnot(const Packet8d& a, - const Packet8d& b) { +EIGEN_STRONG_INLINE Packet8d pandnot(const Packet8d& a,const Packet8d& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ - return _mm512_andnot_pd(a, b); + return _mm512_andnot_pd(b, a); #else - Packet8d res = _mm512_undefined_pd(); - Packet4d lane0_a = _mm512_extractf64x4_pd(a, 0); - Packet4d lane0_b = _mm512_extractf64x4_pd(b, 0); - res = _mm512_insertf64x4(res, _mm256_andnot_pd(lane0_a, lane0_b), 0); - - Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); - Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_andnot_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_castsi512_pd(pandnot(_mm512_castpd_si512(a),_mm512_castpd_si512(b))); #endif } +template EIGEN_STRONG_INLINE Packet16i parithmetic_shift_right(Packet16i a) { + return _mm512_srai_epi32(a, N); +} + +template EIGEN_STRONG_INLINE Packet16i plogical_shift_right(Packet16i a) { + return _mm512_srli_epi32(a, N); +} + +template EIGEN_STRONG_INLINE Packet16i plogical_shift_left(Packet16i a) { + return _mm512_slli_epi32(a, N); +} + template <> EIGEN_STRONG_INLINE Packet16f pload(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm512_load_ps(from); @@ -461,75 +455,55 @@ EIGEN_STRONG_INLINE Packet16i ploadu(const int* from) { // {a0, a0 a1, a1, a2, a2, a3, a3, a4, a4, a5, a5, a6, a6, a7, a7} template <> EIGEN_STRONG_INLINE Packet16f ploaddup(const float* from) { - Packet8f lane0 = _mm256_broadcast_ps((const __m128*)(const void*)from); - // mimic an "inplace" permutation of the lower 128bits using a blend - lane0 = _mm256_blend_ps( - lane0, _mm256_castps128_ps256(_mm_permute_ps( - _mm256_castps256_ps128(lane0), _MM_SHUFFLE(1, 0, 1, 0))), - 15); - // then we can perform a consistent permutation on the global register to get - // everything in shape: - lane0 = _mm256_permute_ps(lane0, _MM_SHUFFLE(3, 3, 2, 2)); - - Packet8f lane1 = _mm256_broadcast_ps((const __m128*)(const void*)(from + 4)); - // mimic an "inplace" permutation of the lower 128bits using a blend - lane1 = _mm256_blend_ps( - lane1, _mm256_castps128_ps256(_mm_permute_ps( - _mm256_castps256_ps128(lane1), _MM_SHUFFLE(1, 0, 1, 0))), - 15); - // then we can perform a consistent permutation on the global register to get - // everything in shape: - lane1 = _mm256_permute_ps(lane1, _MM_SHUFFLE(3, 3, 2, 2)); + // an unaligned load is required here as there is no requirement + // on the alignment of input pointer 'from' + __m256i low_half = _mm256_loadu_si256(reinterpret_cast(from)); + __m512 even_elements = _mm512_castsi512_ps(_mm512_cvtepu32_epi64(low_half)); + __m512 pairs = _mm512_permute_ps(even_elements, _MM_SHUFFLE(2, 2, 0, 0)); + return pairs; +} #ifdef EIGEN_VECTORIZE_AVX512DQ - Packet16f res = _mm512_undefined_ps(); - return _mm512_insertf32x8(res, lane0, 0); - return _mm512_insertf32x8(res, lane1, 1); - return res; -#else - Packet16f res = _mm512_undefined_ps(); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane0, 0), 0); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane0, 1), 1); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane1, 0), 2); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane1, 1), 3); - return res; -#endif -} +// FIXME: this does not look optimal, better load a Packet4d and shuffle... // Loads 4 doubles from memory a returns the packet {a0, a0 a1, a1, a2, a2, a3, // a3} template <> EIGEN_STRONG_INLINE Packet8d ploaddup(const double* from) { - Packet4d lane0 = _mm256_broadcast_pd((const __m128d*)(const void*)from); - lane0 = _mm256_permute_pd(lane0, 3 << 2); - - Packet4d lane1 = _mm256_broadcast_pd((const __m128d*)(const void*)(from + 2)); - lane1 = _mm256_permute_pd(lane1, 3 << 2); - - Packet8d res = _mm512_undefined_pd(); - res = _mm512_insertf64x4(res, lane0, 0); - return _mm512_insertf64x4(res, lane1, 1); + __m512d x = _mm512_setzero_pd(); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[0]), 0); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[1]), 1); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[2]), 2); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[3]), 3); + return x; } +#else +template <> +EIGEN_STRONG_INLINE Packet8d ploaddup(const double* from) { + __m512d x = _mm512_setzero_pd(); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<0, _mm_load_sd(from+0)); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<2, _mm_load_sd(from+1)); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<4, _mm_load_sd(from+2)); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<6, _mm_load_sd(from+3)); + return x; +} +#endif // Loads 4 floats from memory a returns the packet // {a0, a0 a0, a0, a1, a1, a1, a1, a2, a2, a2, a2, a3, a3, a3, a3} template <> EIGEN_STRONG_INLINE Packet16f ploadquad(const float* from) { - Packet16f tmp = _mm512_undefined_ps(); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from), 0); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from + 1), 1); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from + 2), 2); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from + 3), 3); - return tmp; + Packet16f tmp = _mm512_castps128_ps512(ploadu(from)); + const Packet16i scatter_mask = _mm512_set_epi32(3,3,3,3, 2,2,2,2, 1,1,1,1, 0,0,0,0); + return _mm512_permutexvar_ps(scatter_mask, tmp); } + // Loads 2 doubles from memory a returns the packet // {a0, a0 a0, a0, a1, a1, a1, a1} template <> EIGEN_STRONG_INLINE Packet8d ploadquad(const double* from) { - Packet8d tmp = _mm512_undefined_pd(); - Packet2d tmp0 = _mm_load_pd1(from); - Packet2d tmp1 = _mm_load_pd1(from + 1); - Packet4d lane0 = _mm256_broadcastsd_pd(tmp0); - Packet4d lane1 = _mm256_broadcastsd_pd(tmp1); + __m256d lane0 = _mm256_set1_pd(*from); + __m256d lane1 = _mm256_set1_pd(*(from+1)); + __m512d tmp = _mm512_undefined_pd(); tmp = _mm512_insertf64x4(tmp, lane0, 0); return _mm512_insertf64x4(tmp, lane1, 1); } @@ -565,7 +539,7 @@ EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet16i& from) { template <> EIGEN_DEVICE_FUNC inline Packet16f pgather(const float* from, Index stride) { - Packet16i stride_vector = _mm512_set1_epi32(stride); + Packet16i stride_vector = _mm512_set1_epi32(convert_index(stride)); Packet16i stride_multiplier = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); Packet16i indices = _mm512_mullo_epi32(stride_vector, stride_multiplier); @@ -575,7 +549,7 @@ EIGEN_DEVICE_FUNC inline Packet16f pgather(const float* from, template <> EIGEN_DEVICE_FUNC inline Packet8d pgather(const double* from, Index stride) { - Packet8i stride_vector = _mm256_set1_epi32(stride); + Packet8i stride_vector = _mm256_set1_epi32(convert_index(stride)); Packet8i stride_multiplier = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); Packet8i indices = _mm256_mullo_epi32(stride_vector, stride_multiplier); @@ -586,7 +560,7 @@ template <> EIGEN_DEVICE_FUNC inline void pscatter(float* to, const Packet16f& from, Index stride) { - Packet16i stride_vector = _mm512_set1_epi32(stride); + Packet16i stride_vector = _mm512_set1_epi32(convert_index(stride)); Packet16i stride_multiplier = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); Packet16i indices = _mm512_mullo_epi32(stride_vector, stride_multiplier); @@ -596,7 +570,7 @@ template <> EIGEN_DEVICE_FUNC inline void pscatter(double* to, const Packet8d& from, Index stride) { - Packet8i stride_vector = _mm256_set1_epi32(stride); + Packet8i stride_vector = _mm256_set1_epi32(convert_index(stride)); Packet8i stride_multiplier = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); Packet8i indices = _mm256_mullo_epi32(stride_vector, stride_multiplier); _mm512_i32scatter_pd(to, indices, from, 8); @@ -618,9 +592,9 @@ EIGEN_STRONG_INLINE void pstore1(int* to, const int& a) { pstore(to, pa); } -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template <> EIGEN_STRONG_INLINE float pfirst(const Packet16f& a) { @@ -648,20 +622,20 @@ template<> EIGEN_STRONG_INLINE Packet8d preverse(const Packet8d& a) template<> EIGEN_STRONG_INLINE Packet16f pabs(const Packet16f& a) { // _mm512_abs_ps intrinsic not found, so hack around it - return (__m512)_mm512_and_si512((__m512i)a, _mm512_set1_epi32(0x7fffffff)); + return _mm512_castsi512_ps(_mm512_and_si512(_mm512_castps_si512(a), _mm512_set1_epi32(0x7fffffff))); } template <> EIGEN_STRONG_INLINE Packet8d pabs(const Packet8d& a) { // _mm512_abs_ps intrinsic not found, so hack around it - return (__m512d)_mm512_and_si512((__m512i)a, - _mm512_set1_epi64(0x7fffffffffffffff)); + return _mm512_castsi512_pd(_mm512_and_si512(_mm512_castpd_si512(a), + _mm512_set1_epi64(0x7fffffffffffffff))); } #ifdef EIGEN_VECTORIZE_AVX512DQ // AVX512F does not define _mm512_extractf32x8_ps to extract _m256 from _m512 #define EIGEN_EXTRACT_8f_FROM_16f(INPUT, OUTPUT) \ - __m256 OUTPUT##_0 = _mm512_extractf32x8_ps(INPUT, 0) __m256 OUTPUT##_1 = \ - _mm512_extractf32x8_ps(INPUT, 1) + __m256 OUTPUT##_0 = _mm512_extractf32x8_ps(INPUT, 0); \ + __m256 OUTPUT##_1 = _mm512_extractf32x8_ps(INPUT, 1) #else #define EIGEN_EXTRACT_8f_FROM_16f(INPUT, OUTPUT) \ __m256 OUTPUT##_0 = _mm256_insertf128_ps( \ @@ -674,17 +648,136 @@ EIGEN_STRONG_INLINE Packet8d pabs(const Packet8d& a) { #ifdef EIGEN_VECTORIZE_AVX512DQ #define EIGEN_INSERT_8f_INTO_16f(OUTPUT, INPUTA, INPUTB) \ - OUTPUT = _mm512_insertf32x8(OUTPUT, INPUTA, 0); \ - OUTPUT = _mm512_insertf32x8(OUTPUT, INPUTB, 1); + OUTPUT = _mm512_insertf32x8(_mm512_castps256_ps512(INPUTA), INPUTB, 1); #else #define EIGEN_INSERT_8f_INTO_16f(OUTPUT, INPUTA, INPUTB) \ + OUTPUT = _mm512_undefined_ps(); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTA, 0), 0); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTA, 1), 1); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTB, 0), 2); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTB, 1), 3); #endif -template<> EIGEN_STRONG_INLINE Packet16f preduxp(const Packet16f* -vecs) + +template <> +EIGEN_STRONG_INLINE float predux(const Packet16f& a) { +#ifdef EIGEN_VECTORIZE_AVX512DQ + __m256 lane0 = _mm512_extractf32x8_ps(a, 0); + __m256 lane1 = _mm512_extractf32x8_ps(a, 1); + Packet8f x = _mm256_add_ps(lane0, lane1); + return predux(x); +#else + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 sum = _mm_add_ps(_mm_add_ps(lane0, lane1), _mm_add_ps(lane2, lane3)); + sum = _mm_hadd_ps(sum, sum); + sum = _mm_hadd_ps(sum, _mm_permute_ps(sum, 1)); + return _mm_cvtss_f32(sum); +#endif +} +template <> +EIGEN_STRONG_INLINE double predux(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d sum = _mm256_add_pd(lane0, lane1); + __m256d tmp0 = _mm256_hadd_pd(sum, _mm256_permute2f128_pd(sum, sum, 1)); + return _mm_cvtsd_f64(_mm256_castpd256_pd128(_mm256_hadd_pd(tmp0, tmp0))); +} + +template <> +EIGEN_STRONG_INLINE Packet8f predux_downto4(const Packet16f& a) { +#ifdef EIGEN_VECTORIZE_AVX512DQ + Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); + Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); + return padd(lane0, lane1); +#else + Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); + Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); + Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); + Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); + Packet4f sum0 = padd(lane0, lane2); + Packet4f sum1 = padd(lane1, lane3); + return _mm256_insertf128_ps(_mm256_castps128_ps256(sum0), sum1, 1); +#endif +} +template <> +EIGEN_STRONG_INLINE Packet4d predux_downto4(const Packet8d& a) { + Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); + Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); + Packet4d res = padd(lane0, lane1); + return res; +} + +template <> +EIGEN_STRONG_INLINE float predux_mul(const Packet16f& a) { +//#ifdef EIGEN_VECTORIZE_AVX512DQ +#if 0 + Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); + Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); + Packet8f res = pmul(lane0, lane1); + res = pmul(res, _mm256_permute2f128_ps(res, res, 1)); + res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +#else + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 res = pmul(pmul(lane0, lane1), pmul(lane2, lane3)); + res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +#endif +} +template <> +EIGEN_STRONG_INLINE double predux_mul(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d res = pmul(lane0, lane1); + res = pmul(res, _mm256_permute2f128_pd(res, res, 1)); + return pfirst(pmul(res, _mm256_shuffle_pd(res, res, 1))); +} + +template <> +EIGEN_STRONG_INLINE float predux_min(const Packet16f& a) { + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 res = _mm_min_ps(_mm_min_ps(lane0, lane1), _mm_min_ps(lane2, lane3)); + res = _mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(_mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +} +template <> +EIGEN_STRONG_INLINE double predux_min(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d res = _mm256_min_pd(lane0, lane1); + res = _mm256_min_pd(res, _mm256_permute2f128_pd(res, res, 1)); + return pfirst(_mm256_min_pd(res, _mm256_shuffle_pd(res, res, 1))); +} + +template <> +EIGEN_STRONG_INLINE float predux_max(const Packet16f& a) { + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 res = _mm_max_ps(_mm_max_ps(lane0, lane1), _mm_max_ps(lane2, lane3)); + res = _mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(_mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +} + +template <> +EIGEN_STRONG_INLINE double predux_max(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d res = _mm256_max_pd(lane0, lane1); + res = _mm256_max_pd(res, _mm256_permute2f128_pd(res, res, 1)); + return pfirst(_mm256_max_pd(res, _mm256_shuffle_pd(res, res, 1))); +} + +template<> EIGEN_STRONG_INLINE Packet16f preduxp(const Packet16f* vecs) { EIGEN_EXTRACT_8f_FROM_16f(vecs[0], vecs0); EIGEN_EXTRACT_8f_FROM_16f(vecs[1], vecs1); @@ -873,174 +966,7 @@ template<> EIGEN_STRONG_INLINE Packet8d preduxp(const Packet8d* vecs) return _mm512_insertf64x4(final_output, final_1, 1); } - -template <> -EIGEN_STRONG_INLINE float predux(const Packet16f& a) { - //#ifdef EIGEN_VECTORIZE_AVX512DQ -#if 0 - Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); - Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); - Packet8f sum = padd(lane0, lane1); - Packet8f tmp0 = _mm256_hadd_ps(sum, _mm256_permute2f128_ps(a, a, 1)); - tmp0 = _mm256_hadd_ps(tmp0, tmp0); - return pfirst(_mm256_hadd_ps(tmp0, tmp0)); -#else - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f sum = padd(padd(lane0, lane1), padd(lane2, lane3)); - sum = _mm_hadd_ps(sum, sum); - sum = _mm_hadd_ps(sum, _mm_permute_ps(sum, 1)); - return pfirst(sum); -#endif -} -template <> -EIGEN_STRONG_INLINE double predux(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d sum = padd(lane0, lane1); - Packet4d tmp0 = _mm256_hadd_pd(sum, _mm256_permute2f128_pd(sum, sum, 1)); - return pfirst(_mm256_hadd_pd(tmp0, tmp0)); -} - -template <> -EIGEN_STRONG_INLINE Packet8f predux_downto4(const Packet16f& a) { -#ifdef EIGEN_VECTORIZE_AVX512DQ - Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); - Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); - return padd(lane0, lane1); -#else - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f sum0 = padd(lane0, lane2); - Packet4f sum1 = padd(lane1, lane3); - return _mm256_insertf128_ps(_mm256_castps128_ps256(sum0), sum1, 1); -#endif -} -template <> -EIGEN_STRONG_INLINE Packet4d predux_downto4(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = padd(lane0, lane1); - return res; -} - -template <> -EIGEN_STRONG_INLINE float predux_mul(const Packet16f& a) { -//#ifdef EIGEN_VECTORIZE_AVX512DQ -#if 0 - Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); - Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); - Packet8f res = pmul(lane0, lane1); - res = pmul(res, _mm256_permute2f128_ps(res, res, 1)); - res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -#else - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f res = pmul(pmul(lane0, lane1), pmul(lane2, lane3)); - res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -#endif -} -template <> -EIGEN_STRONG_INLINE double predux_mul(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = pmul(lane0, lane1); - res = pmul(res, _mm256_permute2f128_pd(res, res, 1)); - return pfirst(pmul(res, _mm256_shuffle_pd(res, res, 1))); -} - -template <> -EIGEN_STRONG_INLINE float predux_min(const Packet16f& a) { - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f res = _mm_min_ps(_mm_min_ps(lane0, lane1), _mm_min_ps(lane2, lane3)); - res = _mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(_mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -} -template <> -EIGEN_STRONG_INLINE double predux_min(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = _mm256_min_pd(lane0, lane1); - res = _mm256_min_pd(res, _mm256_permute2f128_pd(res, res, 1)); - return pfirst(_mm256_min_pd(res, _mm256_shuffle_pd(res, res, 1))); -} - -template <> -EIGEN_STRONG_INLINE float predux_max(const Packet16f& a) { - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f res = _mm_max_ps(_mm_max_ps(lane0, lane1), _mm_max_ps(lane2, lane3)); - res = _mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(_mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -} -template <> -EIGEN_STRONG_INLINE double predux_max(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = _mm256_max_pd(lane0, lane1); - res = _mm256_max_pd(res, _mm256_permute2f128_pd(res, res, 1)); - return pfirst(_mm256_max_pd(res, _mm256_shuffle_pd(res, res, 1))); -} - -template -struct palign_impl { - static EIGEN_STRONG_INLINE void run(Packet16f& first, - const Packet16f& second) { - if (Offset != 0) { - __m512i first_idx = _mm512_set_epi32( - Offset + 15, Offset + 14, Offset + 13, Offset + 12, Offset + 11, - Offset + 10, Offset + 9, Offset + 8, Offset + 7, Offset + 6, - Offset + 5, Offset + 4, Offset + 3, Offset + 2, Offset + 1, Offset); - - __m512i second_idx = - _mm512_set_epi32(Offset - 1, Offset - 2, Offset - 3, Offset - 4, - Offset - 5, Offset - 6, Offset - 7, Offset - 8, - Offset - 9, Offset - 10, Offset - 11, Offset - 12, - Offset - 13, Offset - 14, Offset - 15, Offset - 16); - - unsigned short mask = 0xFFFF; - mask <<= (16 - Offset); - - first = _mm512_permutexvar_ps(first_idx, first); - Packet16f tmp = _mm512_permutexvar_ps(second_idx, second); - first = _mm512_mask_blend_ps(mask, first, tmp); - } - } -}; -template -struct palign_impl { - static EIGEN_STRONG_INLINE void run(Packet8d& first, const Packet8d& second) { - if (Offset != 0) { - __m512i first_idx = _mm512_set_epi32( - 0, Offset + 7, 0, Offset + 6, 0, Offset + 5, 0, Offset + 4, 0, - Offset + 3, 0, Offset + 2, 0, Offset + 1, 0, Offset); - - __m512i second_idx = _mm512_set_epi32( - 0, Offset - 1, 0, Offset - 2, 0, Offset - 3, 0, Offset - 4, 0, - Offset - 5, 0, Offset - 6, 0, Offset - 7, 0, Offset - 8); - - unsigned char mask = 0xFF; - mask <<= (8 - Offset); - - first = _mm512_permutexvar_pd(first_idx, first); - Packet8d tmp = _mm512_permutexvar_pd(second_idx, second); - first = _mm512_mask_blend_pd(mask, first, tmp); - } - } -}; + #define PACK_OUTPUT(OUTPUT, INPUT, INDEX, STRIDE) \ @@ -1302,13 +1228,76 @@ EIGEN_STRONG_INLINE Packet16f pblend(const Selector<16>& /*ifPacket*/, return Packet16f(); } template <> -EIGEN_STRONG_INLINE Packet8d pblend(const Selector<8>& /*ifPacket*/, - const Packet8d& /*thenPacket*/, - const Packet8d& /*elsePacket*/) { - assert(false && "To be implemented"); - return Packet8d(); +EIGEN_STRONG_INLINE Packet8d pblend(const Selector<8>& ifPacket, + const Packet8d& thenPacket, + const Packet8d& elsePacket) { + __mmask8 m = (ifPacket.select[0] ) + | (ifPacket.select[1]<<1) + | (ifPacket.select[2]<<2) + | (ifPacket.select[3]<<3) + | (ifPacket.select[4]<<4) + | (ifPacket.select[5]<<5) + | (ifPacket.select[6]<<6) + | (ifPacket.select[7]<<7); + return _mm512_mask_blend_pd(m, elsePacket, thenPacket); } +template<> EIGEN_STRONG_INLINE Packet16i pcast(const Packet16f& a) { + return _mm512_cvttps_epi32(a); +} + +template<> EIGEN_STRONG_INLINE Packet16f pcast(const Packet16i& a) { + return _mm512_cvtepi32_ps(a); +} + +template +struct palign_impl { + static EIGEN_STRONG_INLINE void run(Packet16f& first, + const Packet16f& second) { + if (Offset != 0) { + __m512i first_idx = _mm512_set_epi32( + Offset + 15, Offset + 14, Offset + 13, Offset + 12, Offset + 11, + Offset + 10, Offset + 9, Offset + 8, Offset + 7, Offset + 6, + Offset + 5, Offset + 4, Offset + 3, Offset + 2, Offset + 1, Offset); + + __m512i second_idx = + _mm512_set_epi32(Offset - 1, Offset - 2, Offset - 3, Offset - 4, + Offset - 5, Offset - 6, Offset - 7, Offset - 8, + Offset - 9, Offset - 10, Offset - 11, Offset - 12, + Offset - 13, Offset - 14, Offset - 15, Offset - 16); + + unsigned short mask = 0xFFFF; + mask <<= (16 - Offset); + + first = _mm512_permutexvar_ps(first_idx, first); + Packet16f tmp = _mm512_permutexvar_ps(second_idx, second); + first = _mm512_mask_blend_ps(mask, first, tmp); + } + } +}; +template +struct palign_impl { + static EIGEN_STRONG_INLINE void run(Packet8d& first, const Packet8d& second) { + if (Offset != 0) { + __m512i first_idx = _mm512_set_epi32( + 0, Offset + 7, 0, Offset + 6, 0, Offset + 5, 0, Offset + 4, 0, + Offset + 3, 0, Offset + 2, 0, Offset + 1, 0, Offset); + + __m512i second_idx = _mm512_set_epi32( + 0, Offset - 1, 0, Offset - 2, 0, Offset - 3, 0, Offset - 4, 0, + Offset - 5, 0, Offset - 6, 0, Offset - 7, 0, Offset - 8); + + unsigned char mask = 0xFF; + mask <<= (8 - Offset); + + first = _mm512_permutexvar_pd(first_idx, first); + Packet8d tmp = _mm512_permutexvar_pd(second_idx, second); + first = _mm512_mask_blend_pd(mask, first, tmp); + } + } +}; + + } // end namespace internal } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h b/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h index 59367ba2..3e665730 100644 --- a/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h @@ -65,7 +65,7 @@ template<> struct unpacket_traits { typedef std::complex type; template<> EIGEN_STRONG_INLINE Packet2cf pset1(const std::complex& from) { Packet2cf res; - if((ptrdiff_t(&from) % 16) == 0) + if((std::ptrdiff_t(&from) % 16) == 0) res.v = pload((const float *)&from); else res.v = ploadu((const float *)&from); @@ -224,23 +224,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const - { return Packet2cf(internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const - { return Packet2cf(internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { @@ -416,23 +400,8 @@ template<> struct conj_helper return pconj(internal::pmul(a, b)); } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const - { return Packet1cd(internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const - { return Packet1cd(internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { diff --git a/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h b/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h index e7d4f4d8..08a27d15 100755 --- a/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h @@ -90,7 +90,7 @@ static Packet16uc p16uc_DUPLICATE32_HI = { 0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7 }; #define _EIGEN_MASK_ALIGNMENT 0xfffffff0 #endif -#define _EIGEN_ALIGNED_PTR(x) ((ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) +#define _EIGEN_ALIGNED_PTR(x) ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) // Handle endianness properly while loading constants // Define global static constants: @@ -103,7 +103,7 @@ static Packet16uc p16uc_PSET32_WODD = vec_sld((Packet16uc) vec_splat((Packet4u static Packet16uc p16uc_PSET32_WEVEN = vec_sld(p16uc_DUPLICATE32_HI, (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 }; static Packet16uc p16uc_HALF64_0_16 = vec_sld((Packet16uc)p4i_ZERO, vec_splat((Packet16uc) vec_abs(p4i_MINUS16), 3), 8); //{ 0,0,0,0, 0,0,0,0, 16,16,16,16, 16,16,16,16}; #else -static Packet16uc p16uc_FORWARD = p16uc_REVERSE32; +static Packet16uc p16uc_FORWARD = p16uc_REVERSE32; static Packet16uc p16uc_REVERSE64 = { 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 }; static Packet16uc p16uc_PSET32_WODD = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 1), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 }; static Packet16uc p16uc_PSET32_WEVEN = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 }; @@ -388,10 +388,28 @@ template<> EIGEN_STRONG_INLINE Packet4i pdiv(const Packet4i& /*a*/, co template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c) { return vec_madd(a,b,c); } template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return a*b + c; } -template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) { return vec_min(a, b); } +template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) +{ + #ifdef __VSX__ + Packet4f ret; + __asm__ ("xvcmpgesp %x0,%x1,%x2\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + #else + return vec_min(a, b); + #endif +} template<> EIGEN_STRONG_INLINE Packet4i pmin(const Packet4i& a, const Packet4i& b) { return vec_min(a, b); } -template<> EIGEN_STRONG_INLINE Packet4f pmax(const Packet4f& a, const Packet4f& b) { return vec_max(a, b); } +template<> EIGEN_STRONG_INLINE Packet4f pmax(const Packet4f& a, const Packet4f& b) +{ + #ifdef __VSX__ + Packet4f ret; + __asm__ ("xvcmpgtsp %x0,%x2,%x1\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + #else + return vec_max(a, b); + #endif +} template<> EIGEN_STRONG_INLINE Packet4i pmax(const Packet4i& a, const Packet4i& b) { return vec_max(a, b); } template<> EIGEN_STRONG_INLINE Packet4f pand(const Packet4f& a, const Packet4f& b) { return vec_and(a, b); } @@ -450,15 +468,15 @@ template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) { Packet4f p; - if((ptrdiff_t(from) % 16) == 0) p = pload(from); - else p = ploadu(from); + if((std::ptrdiff_t(from) % 16) == 0) p = pload(from); + else p = ploadu(from); return vec_perm(p, p, p16uc_DUPLICATE32_HI); } template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) { Packet4i p; - if((ptrdiff_t(from) % 16) == 0) p = pload(from); - else p = ploadu(from); + if((std::ptrdiff_t(from) % 16) == 0) p = pload(from); + else p = ploadu(from); return vec_perm(p, p, p16uc_DUPLICATE32_HI); } @@ -764,7 +782,7 @@ typedef __vector __bool long Packet2bl; static Packet2l p2l_ONE = { 1, 1 }; static Packet2l p2l_ZERO = reinterpret_cast(p4i_ZERO); -static Packet2d p2d_ONE = { 1.0, 1.0 }; +static Packet2d p2d_ONE = { 1.0, 1.0 }; static Packet2d p2d_ZERO = reinterpret_cast(p4f_ZERO); static Packet2d p2d_MZERO = { -0.0, -0.0 }; @@ -910,9 +928,19 @@ template<> EIGEN_STRONG_INLINE Packet2d pdiv(const Packet2d& a, const // for some weird raisons, it has to be overloaded for packet of integers template<> EIGEN_STRONG_INLINE Packet2d pmadd(const Packet2d& a, const Packet2d& b, const Packet2d& c) { return vec_madd(a, b, c); } -template<> EIGEN_STRONG_INLINE Packet2d pmin(const Packet2d& a, const Packet2d& b) { return vec_min(a, b); } +template<> EIGEN_STRONG_INLINE Packet2d pmin(const Packet2d& a, const Packet2d& b) +{ + Packet2d ret; + __asm__ ("xvcmpgedp %x0,%x1,%x2\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + } -template<> EIGEN_STRONG_INLINE Packet2d pmax(const Packet2d& a, const Packet2d& b) { return vec_max(a, b); } +template<> EIGEN_STRONG_INLINE Packet2d pmax(const Packet2d& a, const Packet2d& b) +{ + Packet2d ret; + __asm__ ("xvcmpgtdp %x0,%x2,%x1\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; +} template<> EIGEN_STRONG_INLINE Packet2d pand(const Packet2d& a, const Packet2d& b) { return vec_and(a, b); } @@ -935,8 +963,8 @@ template<> EIGEN_STRONG_INLINE Packet2d ploadu(const double* from) template<> EIGEN_STRONG_INLINE Packet2d ploaddup(const double* from) { Packet2d p; - if((ptrdiff_t(from) % 16) == 0) p = pload(from); - else p = ploadu(from); + if((std::ptrdiff_t(from) % 16) == 0) p = pload(from); + else p = ploadu(from); return vec_splat_dbl<0>(p); } @@ -969,7 +997,7 @@ template<> EIGEN_STRONG_INLINE Packet2d preduxp(const Packet2d* vecs) Packet2d v[2], sum; v[0] = vecs[0] + reinterpret_cast(vec_sld(reinterpret_cast(vecs[0]), reinterpret_cast(vecs[0]), 8)); v[1] = vecs[1] + reinterpret_cast(vec_sld(reinterpret_cast(vecs[1]), reinterpret_cast(vecs[1]), 8)); - + #ifdef _BIG_ENDIAN sum = reinterpret_cast(vec_sld(reinterpret_cast(v[0]), reinterpret_cast(v[1]), 8)); #else @@ -1022,7 +1050,7 @@ ptranspose(PacketBlock& kernel) { template<> EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket, const Packet2d& elsePacket) { Packet2l select = { ifPacket.select[0], ifPacket.select[1] }; - Packet2bl mask = vec_cmpeq(reinterpret_cast(select), reinterpret_cast(p2l_ONE)); + Packet2bl mask = reinterpret_cast( vec_cmpeq(reinterpret_cast(select), reinterpret_cast(p2l_ONE)) ); return vec_sel(elsePacket, thenPacket, mask); } #endif // __VSX__ diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/Half.h b/eigenlib/Eigen/src/Core/arch/CUDA/Half.h index 52892db3..59717b4f 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/Half.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/Half.h @@ -13,7 +13,7 @@ // Redistribution and use in source and binary forms, with or without // modification, are permitted. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// “AS IS†AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -29,7 +29,7 @@ // type Eigen::half (inheriting from CUDA's __half struct) with // operator overloads such that it behaves basically as an arithmetic // type. It will be quite slow on CPUs (so it is recommended to stay -// in fp32 for CPUs, except for simple parameter conversions, I/O +// in float32_bits for CPUs, except for simple parameter conversions, I/O // to disk and the likes), but fast on GPUs. @@ -42,6 +42,7 @@ #define EIGEN_EXPLICIT_CAST(tgt_type) operator tgt_type() #endif +#include namespace Eigen { @@ -50,38 +51,45 @@ struct half; namespace half_impl { #if !defined(EIGEN_HAS_CUDA_FP16) - -// Make our own __half definition that is similar to CUDA's. -struct __half { - EIGEN_DEVICE_FUNC __half() {} - explicit EIGEN_DEVICE_FUNC __half(unsigned short raw) : x(raw) {} +// Make our own __half_raw definition that is similar to CUDA's. +struct __half_raw { + EIGEN_DEVICE_FUNC __half_raw() : x(0) {} + explicit EIGEN_DEVICE_FUNC __half_raw(unsigned short raw) : x(raw) {} unsigned short x; }; - +#elif defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER < 90000 +// In CUDA < 9.0, __half is the equivalent of CUDA 9's __half_raw +typedef __half __half_raw; #endif -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half raw_uint16_to_half(unsigned short x); -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half float_to_half_rtne(float ff); -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half h); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw raw_uint16_to_half(unsigned short x); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw float_to_half_rtne(float ff); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half_raw h); -struct half_base : public __half { +struct half_base : public __half_raw { EIGEN_DEVICE_FUNC half_base() {} - EIGEN_DEVICE_FUNC half_base(const half_base& h) : __half(h) {} - EIGEN_DEVICE_FUNC half_base(const __half& h) : __half(h) {} + EIGEN_DEVICE_FUNC half_base(const half_base& h) : __half_raw(h) {} + EIGEN_DEVICE_FUNC half_base(const __half_raw& h) : __half_raw(h) {} +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER >= 90000 + EIGEN_DEVICE_FUNC half_base(const __half& h) : __half_raw(*(__half_raw*)&h) {} +#endif }; } // namespace half_impl // Class definition. struct half : public half_impl::half_base { - #if !defined(EIGEN_HAS_CUDA_FP16) - typedef half_impl::__half __half; + #if !defined(EIGEN_HAS_CUDA_FP16) || (defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER < 90000) + typedef half_impl::__half_raw __half_raw; #endif EIGEN_DEVICE_FUNC half() {} - EIGEN_DEVICE_FUNC half(const __half& h) : half_impl::half_base(h) {} + EIGEN_DEVICE_FUNC half(const __half_raw& h) : half_impl::half_base(h) {} EIGEN_DEVICE_FUNC half(const half& h) : half_impl::half_base(h) {} +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER >= 90000 + EIGEN_DEVICE_FUNC half(const __half& h) : half_impl::half_base(h) {} +#endif explicit EIGEN_DEVICE_FUNC half(bool b) : half_impl::half_base(half_impl::raw_uint16_to_half(b ? 0x3c00 : 0)) {} @@ -138,71 +146,125 @@ struct half : public half_impl::half_base { } }; +} // end namespace Eigen + +namespace std { +template<> +struct numeric_limits { + static const bool is_specialized = true; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const bool has_infinity = true; + static const bool has_quiet_NaN = true; + static const bool has_signaling_NaN = true; + static const float_denorm_style has_denorm = denorm_present; + static const bool has_denorm_loss = false; + static const std::float_round_style round_style = std::round_to_nearest; + static const bool is_iec559 = false; + static const bool is_bounded = false; + static const bool is_modulo = false; + static const int digits = 11; + static const int digits10 = 3; // according to http://half.sourceforge.net/structstd_1_1numeric__limits_3_01half__float_1_1half_01_4.html + static const int max_digits10 = 5; // according to http://half.sourceforge.net/structstd_1_1numeric__limits_3_01half__float_1_1half_01_4.html + static const int radix = 2; + static const int min_exponent = -13; + static const int min_exponent10 = -4; + static const int max_exponent = 16; + static const int max_exponent10 = 4; + static const bool traps = true; + static const bool tinyness_before = false; + + static Eigen::half (min)() { return Eigen::half_impl::raw_uint16_to_half(0x400); } + static Eigen::half lowest() { return Eigen::half_impl::raw_uint16_to_half(0xfbff); } + static Eigen::half (max)() { return Eigen::half_impl::raw_uint16_to_half(0x7bff); } + static Eigen::half epsilon() { return Eigen::half_impl::raw_uint16_to_half(0x0800); } + static Eigen::half round_error() { return Eigen::half(0.5); } + static Eigen::half infinity() { return Eigen::half_impl::raw_uint16_to_half(0x7c00); } + static Eigen::half quiet_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); } + static Eigen::half signaling_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); } + static Eigen::half denorm_min() { return Eigen::half_impl::raw_uint16_to_half(0x1); } +}; + +// If std::numeric_limits is specialized, should also specialize +// std::numeric_limits, std::numeric_limits, and +// std::numeric_limits +// https://stackoverflow.com/a/16519653/ +template<> +struct numeric_limits : numeric_limits {}; +template<> +struct numeric_limits : numeric_limits {}; +template<> +struct numeric_limits : numeric_limits {}; +} // end namespace std + +namespace Eigen { + namespace half_impl { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 // Intrinsics for native fp16 support. Note that on current hardware, -// these are no faster than fp32 arithmetic (you need to use the half2 +// these are no faster than float32_bits arithmetic (you need to use the half2 // versions to get the ALU speed increased), but you do save the // conversion steps back and forth. -__device__ half operator + (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator + (const half& a, const half& b) { return __hadd(a, b); } -__device__ half operator * (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator * (const half& a, const half& b) { return __hmul(a, b); } -__device__ half operator - (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator - (const half& a, const half& b) { return __hsub(a, b); } -__device__ half operator / (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator / (const half& a, const half& b) { float num = __half2float(a); float denom = __half2float(b); return __float2half(num / denom); } -__device__ half operator - (const half& a) { +EIGEN_STRONG_INLINE __device__ half operator - (const half& a) { return __hneg(a); } -__device__ half& operator += (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator += (half& a, const half& b) { a = a + b; return a; } -__device__ half& operator *= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator *= (half& a, const half& b) { a = a * b; return a; } -__device__ half& operator -= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator -= (half& a, const half& b) { a = a - b; return a; } -__device__ half& operator /= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator /= (half& a, const half& b) { a = a / b; return a; } -__device__ bool operator == (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator == (const half& a, const half& b) { return __heq(a, b); } -__device__ bool operator != (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator != (const half& a, const half& b) { return __hne(a, b); } -__device__ bool operator < (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator < (const half& a, const half& b) { return __hlt(a, b); } -__device__ bool operator <= (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator <= (const half& a, const half& b) { return __hle(a, b); } -__device__ bool operator > (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator > (const half& a, const half& b) { return __hgt(a, b); } -__device__ bool operator >= (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator >= (const half& a, const half& b) { return __hge(a, b); } #else // Emulate support for half floats // Definitions for CPUs and older CUDA, mostly working through conversion -// to/from fp32. +// to/from float32_bits. EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half operator + (const half& a, const half& b) { return half(float(a) + float(b)); @@ -238,10 +300,10 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half& operator /= (half& a, const half& b) return a; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator == (const half& a, const half& b) { - return float(a) == float(b); + return numext::equal_strict(float(a),float(b)); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator != (const half& a, const half& b) { - return float(a) != float(b); + return numext::not_equal_strict(float(a), float(b)); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator < (const half& a, const half& b) { return float(a) < float(b); @@ -269,34 +331,35 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half operator / (const half& a, Index b) { // these in hardware. If we need more performance on older/other CPUs, they are // also possible to vectorize directly. -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half raw_uint16_to_half(unsigned short x) { - __half h; +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw raw_uint16_to_half(unsigned short x) { + __half_raw h; h.x = x; return h; } -union FP32 { +union float32_bits { unsigned int u; float f; }; -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half float_to_half_rtne(float ff) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300 - return __float2half(ff); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw float_to_half_rtne(float ff) { +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 300 + __half tmp_ff = __float2half(ff); + return *(__half_raw*)&tmp_ff; #elif defined(EIGEN_HAS_FP16_C) - __half h; + __half_raw h; h.x = _cvtss_sh(ff, 0); return h; #else - FP32 f; f.f = ff; + float32_bits f; f.f = ff; - const FP32 f32infty = { 255 << 23 }; - const FP32 f16max = { (127 + 16) << 23 }; - const FP32 denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 }; + const float32_bits f32infty = { 255 << 23 }; + const float32_bits f16max = { (127 + 16) << 23 }; + const float32_bits denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 }; unsigned int sign_mask = 0x80000000u; - __half o; + __half_raw o; o.x = static_cast(0x0u); unsigned int sign = f.u & sign_mask; @@ -335,17 +398,17 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half float_to_half_rtne(float ff) { #endif } -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half h) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300 +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half_raw h) { +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 300 return __half2float(h); #elif defined(EIGEN_HAS_FP16_C) return _cvtsh_ss(h.x); #else - const FP32 magic = { 113 << 23 }; + const float32_bits magic = { 113 << 23 }; const unsigned int shifted_exp = 0x7c00 << 13; // exponent mask after shift - FP32 o; + float32_bits o; o.u = (h.x & 0x7fff) << 13; // exponent/mantissa bits unsigned int exp = shifted_exp & o.u; // just the exponent @@ -370,7 +433,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool (isinf)(const half& a) { return (a.x & 0x7fff) == 0x7c00; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool (isnan)(const half& a) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return __hisnan(a); #else return (a.x & 0x7fff) > 0x7c00; @@ -386,11 +449,15 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half& a) { return result; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half exp(const half& a) { - return half(::expf(float(a))); +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 + return half(hexp(a)); +#else + return half(::expf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log(const half& a) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 - return Eigen::half(::hlog(a)); +#if defined(EIGEN_HAS_CUDA_FP16) && EIGEN_CUDACC_VER >= 80000 && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 + return half(::hlog(a)); #else return half(::logf(float(a))); #endif @@ -402,7 +469,11 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log10(const half& a) { return half(::log10f(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half sqrt(const half& a) { - return half(::sqrtf(float(a))); +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 + return half(hsqrt(a)); +#else + return half(::sqrtf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half pow(const half& a, const half& b) { return half(::powf(float(a), float(b))); @@ -420,14 +491,22 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half tanh(const half& a) { return half(::tanhf(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half floor(const half& a) { +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 300 + return half(hfloor(a)); +#else return half(::floorf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half ceil(const half& a) { +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 300 + return half(hceil(a)); +#else return half(::ceilf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (min)(const half& a, const half& b) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return __hlt(b, a) ? b : a; #else const float f1 = static_cast(a); @@ -436,7 +515,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (min)(const half& a, const half& b) { #endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (max)(const half& a, const half& b) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return __hlt(a, b) ? b : a; #else const float f1 = static_cast(a); @@ -477,6 +556,13 @@ template<> struct is_arithmetic { enum { value = true }; }; template<> struct NumTraits : GenericNumTraits { + enum { + IsSigned = true, + IsInteger = false, + IsComplex = false, + RequireInitialization = false + }; + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half epsilon() { return half_impl::raw_uint16_to_half(0x0800); } @@ -507,7 +593,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half exph(const Eigen::half& a) { return Eigen::half(::expf(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half logh(const Eigen::half& a) { -#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if EIGEN_CUDACC_VER >= 80000 && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return Eigen::half(::hlog(a)); #else return Eigen::half(::logf(float(a))); @@ -541,14 +627,18 @@ struct hash { // Add the missing shfl_xor intrinsic -#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300 +#if defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 300 __device__ EIGEN_STRONG_INLINE Eigen::half __shfl_xor(Eigen::half var, int laneMask, int width=warpSize) { + #if EIGEN_CUDACC_VER < 90000 return static_cast(__shfl_xor(static_cast(var), laneMask, width)); + #else + return static_cast(__shfl_xor_sync(0xFFFFFFFF, static_cast(var), laneMask, width)); + #endif } #endif -// ldg() has an overload for __half, but we also need one for Eigen::half. -#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 350 +// ldg() has an overload for __half_raw, but we also need one for Eigen::half. +#if defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 350 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half __ldg(const Eigen::half* ptr) { return Eigen::half_impl::raw_uint16_to_half( __ldg(reinterpret_cast(ptr))); @@ -556,7 +646,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half __ldg(const Eigen::half* ptr) #endif -#if defined(__CUDA_ARCH__) +#if defined(EIGEN_CUDA_ARCH) namespace Eigen { namespace numext { diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h index ad66399e..4dda6318 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h @@ -291,7 +291,7 @@ template<> EIGEN_DEVICE_FUNC inline double2 pabs(const double2& a) { EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock& kernel) { - double tmp = kernel.packet[0].y; + float tmp = kernel.packet[0].y; kernel.packet[0].y = kernel.packet[1].x; kernel.packet[1].x = tmp; diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h index ae54225f..f749c573 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h @@ -99,7 +99,8 @@ template<> __device__ EIGEN_STRONG_INLINE Eigen::half pfirst(const half2& template<> __device__ EIGEN_STRONG_INLINE half2 pabs(const half2& a) { half2 result; - result.x = a.x & 0x7FFF7FFF; + unsigned temp = *(reinterpret_cast(&(a))); + *(reinterpret_cast(&(result))) = temp & 0x7FFF7FFF; return result; } @@ -229,7 +230,7 @@ template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux(const half2& #else float a1 = __low2float(a); float a2 = __high2float(a); - return Eigen::half(half_impl::raw_uint16_to_half(__float2half_rn(a1 + a2))); + return Eigen::half(__float2half_rn(a1 + a2)); #endif } @@ -263,7 +264,7 @@ template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux_mul(const ha #else float a1 = __low2float(a); float a2 = __high2float(a); - return Eigen::half(half_impl::raw_uint16_to_half(__float2half_rn(a1 * a2))); + return Eigen::half(__float2half_rn(a1 * a2)); #endif } @@ -275,7 +276,7 @@ template<> __device__ EIGEN_STRONG_INLINE half2 plog1p(const half2& a) { return __floats2half2_rn(r1, r2); } -#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 530 +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 template<> __device__ EIGEN_STRONG_INLINE half2 plog(const half2& a) { diff --git a/eigenlib/Eigen/src/Core/arch/Default/ConjHelper.h b/eigenlib/Eigen/src/Core/arch/Default/ConjHelper.h new file mode 100644 index 00000000..4cfe34e0 --- /dev/null +++ b/eigenlib/Eigen/src/Core/arch/Default/ConjHelper.h @@ -0,0 +1,29 @@ + +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2017 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ARCH_CONJ_HELPER_H +#define EIGEN_ARCH_CONJ_HELPER_H + +#define EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PACKET_CPLX, PACKET_REAL) \ + template<> struct conj_helper { \ + EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_REAL& x, const PACKET_CPLX& y, const PACKET_CPLX& c) const \ + { return padd(c, pmul(x,y)); } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_REAL& x, const PACKET_CPLX& y) const \ + { return PACKET_CPLX(Eigen::internal::pmul(x, y.v)); } \ + }; \ + \ + template<> struct conj_helper { \ + EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_CPLX& x, const PACKET_REAL& y, const PACKET_CPLX& c) const \ + { return padd(c, pmul(x,y)); } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_CPLX& x, const PACKET_REAL& y) const \ + { return PACKET_CPLX(Eigen::internal::pmul(x.v, y)); } \ + }; + +#endif // EIGEN_ARCH_CONJ_HELPER_H diff --git a/eigenlib/Eigen/src/Core/arch/NEON/Complex.h b/eigenlib/Eigen/src/Core/arch/NEON/Complex.h index 57e9b431..306a309b 100644 --- a/eigenlib/Eigen/src/Core/arch/NEON/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/NEON/Complex.h @@ -67,7 +67,7 @@ template<> struct unpacket_traits { typedef std::complex type; template<> EIGEN_STRONG_INLINE Packet2cf pset1(const std::complex& from) { float32x2_t r64; - r64 = vld1_f32((float *)&from); + r64 = vld1_f32((const float *)&from); return Packet2cf(vcombine_f32(r64, r64)); } @@ -142,7 +142,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter, Packet2cf to[stride*1] = std::complex(vgetq_lane_f32(from.v, 2), vgetq_lane_f32(from.v, 3)); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((float *)addr); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((const float *)addr); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet2cf& a) { @@ -265,6 +265,8 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) + template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { // TODO optimize it for NEON @@ -275,7 +277,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, con s = vmulq_f32(b.v, b.v); rev_s = vrev64q_f32(s); - return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s))); + return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s))); } EIGEN_DEVICE_FUNC inline void @@ -381,7 +383,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd ploaddup(const std::complex< template<> EIGEN_STRONG_INLINE void pstore >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, from.v); } template<> EIGEN_STRONG_INLINE void pstoreu >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((double *)addr); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((const double *)addr); } template<> EIGEN_DEVICE_FUNC inline Packet1cd pgather, Packet1cd>(const std::complex* from, Index stride) { @@ -456,6 +458,8 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) + template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { // TODO optimize it for NEON diff --git a/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h b/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h index d392bf3f..3d5ed0d2 100644 --- a/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h @@ -36,29 +36,63 @@ namespace internal { #endif #endif +#if EIGEN_COMP_MSVC + +// In MSVC's arm_neon.h header file, all NEON vector types +// are aliases to the same underlying type __n128. +// We thus have to wrap them to make them different C++ types. +// (See also bug 1428) + +template +struct eigen_packet_wrapper +{ + operator T&() { return m_val; } + operator const T&() const { return m_val; } + eigen_packet_wrapper() {} + eigen_packet_wrapper(const T &v) : m_val(v) {} + eigen_packet_wrapper& operator=(const T &v) { + m_val = v; + return *this; + } + + T m_val; +}; +typedef eigen_packet_wrapper Packet2f; +typedef eigen_packet_wrapper Packet4f; +typedef eigen_packet_wrapper Packet4i; +typedef eigen_packet_wrapper Packet2i; +typedef eigen_packet_wrapper Packet4ui; + +#else + typedef float32x2_t Packet2f; typedef float32x4_t Packet4f; typedef int32x4_t Packet4i; typedef int32x2_t Packet2i; typedef uint32x4_t Packet4ui; +#endif // EIGEN_COMP_MSVC + #define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \ const Packet4f p4f_##NAME = pset1(X) #define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \ - const Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1(X)) + const Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1(X)) #define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \ const Packet4i p4i_##NAME = pset1(X) -// arm64 does have the pld instruction. If available, let's trust the __builtin_prefetch built-in function -// which available on LLVM and GCC (at least) -#if EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC +#if EIGEN_ARCH_ARM64 + // __builtin_prefetch tends to do nothing on ARM64 compilers because the + // prefetch instructions there are too detailed for __builtin_prefetch to map + // meaningfully to them. + #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__("prfm pldl1keep, [%[addr]]\n" ::[addr] "r"(ADDR) : ); +#elif EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC #define EIGEN_ARM_PREFETCH(ADDR) __builtin_prefetch(ADDR); #elif defined __pld #define EIGEN_ARM_PREFETCH(ADDR) __pld(ADDR) -#elif !EIGEN_ARCH_ARM64 - #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ( " pld [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" ); +#elif EIGEN_ARCH_ARM32 + #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ("pld [%[addr]]\n" :: [addr] "r" (ADDR) : ); #else // by default no explicit prefetching #define EIGEN_ARM_PREFETCH(ADDR) @@ -83,7 +117,7 @@ template<> struct packet_traits : default_packet_traits HasSqrt = 0 }; }; -template<> struct packet_traits : default_packet_traits +template<> struct packet_traits : default_packet_traits { typedef Packet4i type; typedef Packet4i half; // Packet2i intrinsics not implemented yet @@ -105,19 +139,19 @@ EIGEN_STRONG_INLINE void vst1q_f32(float* to, float32x4_t from) { ::vst1q EIGEN_STRONG_INLINE void vst1_f32 (float* to, float32x2_t from) { ::vst1_f32 ((float32_t*)to,from); } #endif -template<> struct unpacket_traits { typedef float type; enum {size=4, alignment=Aligned16}; typedef Packet4f half; }; -template<> struct unpacket_traits { typedef int type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; }; +template<> struct unpacket_traits { typedef float type; enum {size=4, alignment=Aligned16}; typedef Packet4f half; }; +template<> struct unpacket_traits { typedef int32_t type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; }; template<> EIGEN_STRONG_INLINE Packet4f pset1(const float& from) { return vdupq_n_f32(from); } -template<> EIGEN_STRONG_INLINE Packet4i pset1(const int& from) { return vdupq_n_s32(from); } +template<> EIGEN_STRONG_INLINE Packet4i pset1(const int32_t& from) { return vdupq_n_s32(from); } template<> EIGEN_STRONG_INLINE Packet4f plset(const float& a) { - const float32_t f[] = {0, 1, 2, 3}; + const float f[] = {0, 1, 2, 3}; Packet4f countdown = vld1q_f32(f); return vaddq_f32(pset1(a), countdown); } -template<> EIGEN_STRONG_INLINE Packet4i plset(const int& a) +template<> EIGEN_STRONG_INLINE Packet4i plset(const int32_t& a) { const int32_t i[] = {0, 1, 2, 3}; Packet4i countdown = vld1q_s32(i); @@ -240,20 +274,20 @@ template<> EIGEN_STRONG_INLINE Packet4f pandnot(const Packet4f& a, con } template<> EIGEN_STRONG_INLINE Packet4i pandnot(const Packet4i& a, const Packet4i& b) { return vbicq_s32(a,b); } -template<> EIGEN_STRONG_INLINE Packet4f pload(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_f32(from); } -template<> EIGEN_STRONG_INLINE Packet4i pload(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_s32(from); } +template<> EIGEN_STRONG_INLINE Packet4f pload(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_f32(from); } +template<> EIGEN_STRONG_INLINE Packet4i pload(const int32_t* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_s32(from); } -template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_f32(from); } -template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_s32(from); } +template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_f32(from); } +template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int32_t* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_s32(from); } -template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) +template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) { float32x2_t lo, hi; lo = vld1_dup_f32(from); hi = vld1_dup_f32(from+1); return vcombine_f32(lo, hi); } -template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) +template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int32_t* from) { int32x2_t lo, hi; lo = vld1_dup_s32(from); @@ -261,11 +295,11 @@ template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) return vcombine_s32(lo, hi); } -template<> EIGEN_STRONG_INLINE void pstore(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_f32(to, from); } -template<> EIGEN_STRONG_INLINE void pstore(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_s32(to, from); } +template<> EIGEN_STRONG_INLINE void pstore (float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_f32(to, from); } +template<> EIGEN_STRONG_INLINE void pstore(int32_t* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_s32(to, from); } -template<> EIGEN_STRONG_INLINE void pstoreu(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); } -template<> EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); } +template<> EIGEN_STRONG_INLINE void pstoreu (float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); } +template<> EIGEN_STRONG_INLINE void pstoreu(int32_t* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); } template<> EIGEN_DEVICE_FUNC inline Packet4f pgather(const float* from, Index stride) { @@ -276,7 +310,7 @@ template<> EIGEN_DEVICE_FUNC inline Packet4f pgather(const floa res = vsetq_lane_f32(from[3*stride], res, 3); return res; } -template<> EIGEN_DEVICE_FUNC inline Packet4i pgather(const int* from, Index stride) +template<> EIGEN_DEVICE_FUNC inline Packet4i pgather(const int32_t* from, Index stride) { Packet4i res = pset1(0); res = vsetq_lane_s32(from[0*stride], res, 0); @@ -293,7 +327,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter(float* to, co to[stride*2] = vgetq_lane_f32(from, 2); to[stride*3] = vgetq_lane_f32(from, 3); } -template<> EIGEN_DEVICE_FUNC inline void pscatter(int* to, const Packet4i& from, Index stride) +template<> EIGEN_DEVICE_FUNC inline void pscatter(int32_t* to, const Packet4i& from, Index stride) { to[stride*0] = vgetq_lane_s32(from, 0); to[stride*1] = vgetq_lane_s32(from, 1); @@ -301,12 +335,12 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter(int* to, const to[stride*3] = vgetq_lane_s32(from, 3); } -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { EIGEN_ARM_PREFETCH(addr); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { EIGEN_ARM_PREFETCH(addr); } +template<> EIGEN_STRONG_INLINE void prefetch (const float* addr) { EIGEN_ARM_PREFETCH(addr); } +template<> EIGEN_STRONG_INLINE void prefetch(const int32_t* addr) { EIGEN_ARM_PREFETCH(addr); } // FIXME only store the 2 first elements ? -template<> EIGEN_STRONG_INLINE float pfirst(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; } -template<> EIGEN_STRONG_INLINE int pfirst(const Packet4i& a) { int EIGEN_ALIGN16 x[4]; vst1q_s32(x, a); return x[0]; } +template<> EIGEN_STRONG_INLINE float pfirst(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; } +template<> EIGEN_STRONG_INLINE int32_t pfirst(const Packet4i& a) { int32_t EIGEN_ALIGN16 x[4]; vst1q_s32(x, a); return x[0]; } template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a) { float32x2_t a_lo, a_hi; @@ -361,7 +395,7 @@ template<> EIGEN_STRONG_INLINE Packet4f preduxp(const Packet4f* vecs) return sum; } -template<> EIGEN_STRONG_INLINE int predux(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux(const Packet4i& a) { int32x2_t a_lo, a_hi, sum; @@ -408,7 +442,7 @@ template<> EIGEN_STRONG_INLINE float predux_mul(const Packet4f& a) return vget_lane_f32(prod, 0); } -template<> EIGEN_STRONG_INLINE int predux_mul(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux_mul(const Packet4i& a) { int32x2_t a_lo, a_hi, prod; @@ -436,7 +470,7 @@ template<> EIGEN_STRONG_INLINE float predux_min(const Packet4f& a) return vget_lane_f32(min, 0); } -template<> EIGEN_STRONG_INLINE int predux_min(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux_min(const Packet4i& a) { int32x2_t a_lo, a_hi, min; @@ -461,7 +495,7 @@ template<> EIGEN_STRONG_INLINE float predux_max(const Packet4f& a) return vget_lane_f32(max, 0); } -template<> EIGEN_STRONG_INLINE int predux_max(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux_max(const Packet4i& a) { int32x2_t a_lo, a_hi, max; diff --git a/eigenlib/Eigen/src/Core/arch/SSE/Complex.h b/eigenlib/Eigen/src/Core/arch/SSE/Complex.h index 5607fe0a..d075043c 100644 --- a/eigenlib/Eigen/src/Core/arch/SSE/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/SSE/Complex.h @@ -128,7 +128,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter, Packet2cf _mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 3))); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet2cf& a) { @@ -229,23 +229,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const - { return Packet2cf(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const - { return Packet2cf(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { @@ -340,7 +324,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd ploaddup(const std::complex< template<> EIGEN_STRONG_INLINE void pstore >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, Packet2d(from.v)); } template<> EIGEN_STRONG_INLINE void pstoreu >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, Packet2d(from.v)); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet1cd& a) { @@ -430,23 +414,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const - { return Packet1cd(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const - { return Packet1cd(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { diff --git a/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h b/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h index 3832de14..60e2517e 100755 --- a/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h @@ -28,7 +28,7 @@ namespace internal { #endif #endif -#if (defined EIGEN_VECTORIZE_AVX) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_MINGW) && (__GXX_ABI_VERSION < 1004) +#if ((defined EIGEN_VECTORIZE_AVX) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_MINGW) && (__GXX_ABI_VERSION < 1004)) || EIGEN_OS_QNX // With GCC's default ABI version, a __m128 or __m256 are the same types and therefore we cannot // have overloads for both types without linking error. // One solution is to increase ABI version using -fabi-version=4 (or greater). @@ -409,10 +409,16 @@ template<> EIGEN_STRONG_INLINE void pstore1(double* to, const double& pstore(to, Packet2d(vec2d_swizzle1(pa,0,0))); } +#if EIGEN_COMP_PGI +typedef const void * SsePrefetchPtrType; +#else +typedef const char * SsePrefetchPtrType; +#endif + #ifndef EIGEN_VECTORIZE_AVX -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } #endif #if EIGEN_COMP_MSVC_STRICT && EIGEN_OS_WIN64 @@ -876,4 +882,14 @@ template<> EIGEN_STRONG_INLINE double pmadd(const double& a, const double& b, co } // end namespace Eigen +#if EIGEN_COMP_PGI +// PGI++ does not define the following intrinsics in C++ mode. +static inline __m128 _mm_castpd_ps (__m128d x) { return reinterpret_cast<__m128&>(x); } +static inline __m128i _mm_castpd_si128(__m128d x) { return reinterpret_cast<__m128i&>(x); } +static inline __m128d _mm_castps_pd (__m128 x) { return reinterpret_cast<__m128d&>(x); } +static inline __m128i _mm_castps_si128(__m128 x) { return reinterpret_cast<__m128i&>(x); } +static inline __m128 _mm_castsi128_ps(__m128i x) { return reinterpret_cast<__m128&>(x); } +static inline __m128d _mm_castsi128_pd(__m128i x) { return reinterpret_cast<__m128d&>(x); } +#endif + #endif // EIGEN_PACKET_MATH_SSE_H diff --git a/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h b/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h index c8489323..c6ca8c71 100644 --- a/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h +++ b/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h @@ -14,6 +14,7 @@ namespace Eigen { namespace internal { +#ifndef EIGEN_VECTORIZE_AVX template <> struct type_casting_traits { enum { @@ -23,11 +24,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4i pcast(const Packet4f& a) { - return _mm_cvttps_epi32(a); -} - - template <> struct type_casting_traits { enum { @@ -37,11 +33,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet4i& a) { - return _mm_cvtepi32_ps(a); -} - - template <> struct type_casting_traits { enum { @@ -51,10 +42,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet2d& a, const Packet2d& b) { - return _mm_shuffle_ps(_mm_cvtpd_ps(a), _mm_cvtpd_ps(b), (1 << 2) | (1 << 6)); -} - template <> struct type_casting_traits { enum { @@ -63,6 +50,19 @@ struct type_casting_traits { TgtCoeffRatio = 2 }; }; +#endif + +template<> EIGEN_STRONG_INLINE Packet4i pcast(const Packet4f& a) { + return _mm_cvttps_epi32(a); +} + +template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet4i& a) { + return _mm_cvtepi32_ps(a); +} + +template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet2d& a, const Packet2d& b) { + return _mm_shuffle_ps(_mm_cvtpd_ps(a), _mm_cvtpd_ps(b), (1 << 2) | (1 << 6)); +} template<> EIGEN_STRONG_INLINE Packet2d pcast(const Packet4f& a) { // Simply discard the second half of the input diff --git a/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h b/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h index d39d2d10..1bfb7339 100644 --- a/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h @@ -336,6 +336,9 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) + template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { // TODO optimize it for AltiVec diff --git a/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h b/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h index e2deb25c..57b01fc6 100755 --- a/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h @@ -100,7 +100,7 @@ static Packet16uc p16uc_DUPLICATE32_HI = { 0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7 }; // Mask alignment #define _EIGEN_MASK_ALIGNMENT 0xfffffffffffffff0 -#define _EIGEN_ALIGNED_PTR(x) ((ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) +#define _EIGEN_ALIGNED_PTR(x) ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) // Handle endianness properly while loading constants // Define global static constants: diff --git a/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h b/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h index 9b373c78..4153b877 100644 --- a/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h @@ -28,7 +28,7 @@ template struct assign_op { { internal::pstoret(a,b); } }; -// Empty overload for void type (used by PermutationMatrix +// Empty overload for void type (used by PermutationMatrix) template struct assign_op {}; template diff --git a/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h b/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h index 96747bac..3eae6b8c 100644 --- a/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h @@ -255,7 +255,7 @@ struct scalar_cmp_op : binary_op_base struct scalar_hypot_op : binary_op_base { EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op) -// typedef typename NumTraits::Real result_type; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar &x, const Scalar &y) const { - EIGEN_USING_STD_MATH(sqrt) - Scalar p, qp; - if(_x>_y) - { - p = _x; - qp = _y / p; - } - else - { - p = _y; - qp = _x / p; - } - return p * sqrt(Scalar(1) + qp*qp); + // This functor is used by hypotNorm only for which it is faster to first apply abs + // on all coefficients prior to reduction through hypot. + // This way we avoid calling abs on positive and real entries, and this also permits + // to seamlessly handle complexes. Otherwise we would have to handle both real and complexes + // through the same functor... + return internal::positive_real_hypot(x,y); } }; template diff --git a/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h b/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h index 0311d903..b03be026 100644 --- a/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h @@ -44,16 +44,16 @@ struct linspaced_op_impl { linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) : m_low(low), m_high(high), m_size1(num_steps==1 ? 1 : num_steps-1), m_step(num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1)), - m_interPacket(plset(0)), m_flip(numext::abs(high) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType i) const { + typedef typename NumTraits::Real RealScalar; if(m_flip) - return (i==0)? m_low : (m_high - (m_size1-i)*m_step); + return (i==0)? m_low : (m_high - RealScalar(m_size1-i)*m_step); else - return (i==m_size1)? m_high : (m_low + i*m_step); + return (i==m_size1)? m_high : (m_low + RealScalar(i)*m_step); } template @@ -63,7 +63,7 @@ struct linspaced_op_impl // [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) ) if(m_flip) { - Packet pi = padd(pset1(Scalar(i-m_size1)),m_interPacket); + Packet pi = plset(Scalar(i-m_size1)); Packet res = padd(pset1(m_high), pmul(pset1(m_step), pi)); if(i==0) res = pinsertfirst(res, m_low); @@ -71,7 +71,7 @@ struct linspaced_op_impl } else { - Packet pi = padd(pset1(Scalar(i)),m_interPacket); + Packet pi = plset(Scalar(i)); Packet res = padd(pset1(m_low), pmul(pset1(m_step), pi)); if(i==m_size1-unpacket_traits::size+1) res = pinsertlast(res, m_high); @@ -83,7 +83,6 @@ struct linspaced_op_impl const Scalar m_high; const Index m_size1; const Scalar m_step; - const Packet m_interPacket; const bool m_flip; }; @@ -93,8 +92,8 @@ struct linspaced_op_impl linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) : m_low(low), m_multiplier((high-low)/convert_index(num_steps<=1 ? 1 : num_steps-1)), - m_divisor(convert_index(num_steps+high-low)/(high-low+1)), - m_use_divisor((high+1)<(low+num_steps)) + m_divisor(convert_index((high>=low?num_steps:-num_steps)+(high-low))/((numext::abs(high-low)+1)==0?1:(numext::abs(high-low)+1))), + m_use_divisor(num_steps>1 && (numext::abs(high-low)+1) diff --git a/eigenlib/Eigen/src/Core/functors/StlFunctors.h b/eigenlib/Eigen/src/Core/functors/StlFunctors.h index 6df3fa50..9c1d7585 100644 --- a/eigenlib/Eigen/src/Core/functors/StlFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/StlFunctors.h @@ -83,13 +83,17 @@ struct functor_traits > { enum { Cost = functor_traits::Cost, PacketAccess = false }; }; #endif +#if (__cplusplus < 201703L) && (EIGEN_COMP_MSVC < 1910) +// std::unary_negate is deprecated since c++17 and will be removed in c++20 template struct functor_traits > { enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; +// std::binary_negate is deprecated since c++17 and will be removed in c++20 template struct functor_traits > { enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; +#endif #ifdef EIGEN_STDEXT_SUPPORT diff --git a/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h b/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h index 2e6a00ff..b56e7afd 100644 --- a/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h @@ -768,7 +768,7 @@ struct scalar_sign_op { if (aa==real_type(0)) return Scalar(0); aa = real_type(1)/aa; - return Scalar(real(a)*aa, imag(a)*aa ); + return Scalar(a.real()*aa, a.imag()*aa ); } //TODO //template diff --git a/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h index 45230bce..681451cc 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h +++ b/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h @@ -115,7 +115,8 @@ void evaluateProductBlockingSizesHeuristic(Index& k, Index& m, Index& n, Index n // registers. However once the latency is hidden there is no point in // increasing the value of k, so we'll cap it at 320 (value determined // experimentally). - const Index k_cache = (numext::mini)((l1-ksub)/kdiv, 320); + // To avoid that k vanishes, we make k_cache at least as big as kr + const Index k_cache = numext::maxi(kr, (numext::mini)((l1-ksub)/kdiv, 320)); if (k_cache < k) { k = k_cache - (k_cache % kr); eigen_internal_assert(k > 0); @@ -648,8 +649,8 @@ public: // Vectorized path EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, DoublePacketType& dest) const { - dest.first = pset1(real(*b)); - dest.second = pset1(imag(*b)); + dest.first = pset1(numext::real(*b)); + dest.second = pset1(numext::imag(*b)); } EIGEN_STRONG_INLINE void loadRhsQuad(const RhsScalar* b, ResPacket& dest) const @@ -1197,10 +1198,16 @@ void gebp_kernel=6 without FMA (bug 1637) + #if EIGEN_GNUC_AT_LEAST(6,0) && defined(EIGEN_VECTORIZE_SSE) + #define EIGEN_GEBP_2PX4_SPILLING_WORKAROUND __asm__ ("" : [a0] "+x,m" (A0),[a1] "+x,m" (A1)); + #else + #define EIGEN_GEBP_2PX4_SPILLING_WORKAROUND + #endif + #define EIGEN_GEBGP_ONESTEP(K) \ do { \ EIGEN_ASM_COMMENT("begin step of gebp micro kernel 2pX4"); \ - EIGEN_ASM_COMMENT("Note: these asm comments work around bug 935!"); \ traits.loadLhs(&blA[(0+2*K)*LhsProgress], A0); \ traits.loadLhs(&blA[(1+2*K)*LhsProgress], A1); \ traits.broadcastRhs(&blB[(0+4*K)*RhsProgress], B_0, B1, B2, B3); \ @@ -1212,6 +1219,7 @@ void gebp_kernel::half SResPacketHalf; + const int SResPacketHalfSize = unpacket_traits::half>::size; if ((SwappedTraits::LhsProgress % 4) == 0 && (SwappedTraits::LhsProgress <= 8) && - (SwappedTraits::LhsProgress!=8 || unpacket_traits::size==nr)) + (SwappedTraits::LhsProgress!=8 || SResPacketHalfSize==nr)) { SAccPacket C0, C1, C2, C3; straits.initAcc(C0); diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h index 61df3be5..ed6234c3 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h @@ -20,8 +20,9 @@ template class level3_blocking; template< typename Index, typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs, - typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs> -struct general_matrix_matrix_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct general_matrix_matrix_product { typedef gebp_traits Traits; @@ -30,7 +31,7 @@ struct general_matrix_matrix_product& blocking, GemmParallelInfo* info = 0) @@ -39,8 +40,8 @@ struct general_matrix_matrix_product - ::run(cols,rows,depth,rhs,rhsStride,lhs,lhsStride,res,resStride,alpha,blocking,info); + ColMajor,ResInnerStride> + ::run(cols,rows,depth,rhs,rhsStride,lhs,lhsStride,res,resIncr,resStride,alpha,blocking,info); } }; @@ -49,8 +50,9 @@ struct general_matrix_matrix_product -struct general_matrix_matrix_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct general_matrix_matrix_product { typedef gebp_traits Traits; @@ -59,17 +61,17 @@ typedef typename ScalarBinaryOpTraits::ReturnType ResScala static void run(Index rows, Index cols, Index depth, const LhsScalar* _lhs, Index lhsStride, const RhsScalar* _rhs, Index rhsStride, - ResScalar* _res, Index resStride, + ResScalar* _res, Index resIncr, Index resStride, ResScalar alpha, level3_blocking& blocking, GemmParallelInfo* info = 0) { typedef const_blas_data_mapper LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; - LhsMapper lhs(_lhs,lhsStride); - RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + typedef blas_data_mapper ResMapper; + LhsMapper lhs(_lhs, lhsStride); + RhsMapper rhs(_rhs, rhsStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -83,8 +85,8 @@ static void run(Index rows, Index cols, Index depth, if(info) { // this is the parallel version! - Index tid = omp_get_thread_num(); - Index threads = omp_get_num_threads(); + int tid = omp_get_thread_num(); + int threads = omp_get_num_threads(); LhsScalar* blockA = blocking.blockA(); eigen_internal_assert(blockA!=0); @@ -116,9 +118,9 @@ static void run(Index rows, Index cols, Index depth, info[tid].sync = k; // Computes C_i += A' * B' per A'_i - for(Index shift=0; shift static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { if((rhs.rows()+dst.rows()+dst.cols())<20 && rhs.rows()>0) - lazyproduct::evalTo(dst, lhs, rhs); + lazyproduct::eval_dynamic(dst, lhs, rhs, internal::assign_op()); else { dst.setZero(); @@ -440,7 +442,7 @@ struct generic_product_impl static void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { if((rhs.rows()+dst.rows()+dst.cols())<20 && rhs.rows()>0) - lazyproduct::addTo(dst, lhs, rhs); + lazyproduct::eval_dynamic(dst, lhs, rhs, internal::add_assign_op()); else scaleAndAddTo(dst,lhs, rhs, Scalar(1)); } @@ -449,7 +451,7 @@ struct generic_product_impl static void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { if((rhs.rows()+dst.rows()+dst.cols())<20 && rhs.rows()>0) - lazyproduct::subTo(dst, lhs, rhs); + lazyproduct::eval_dynamic(dst, lhs, rhs, internal::sub_assign_op()); else scaleAndAddTo(dst, lhs, rhs, Scalar(-1)); } @@ -476,7 +478,8 @@ struct generic_product_impl Index, LhsScalar, (ActualLhsTypeCleaned::Flags&RowMajorBit) ? RowMajor : ColMajor, bool(LhsBlasTraits::NeedToConjugate), RhsScalar, (ActualRhsTypeCleaned::Flags&RowMajorBit) ? RowMajor : ColMajor, bool(RhsBlasTraits::NeedToConjugate), - (Dest::Flags&RowMajorBit) ? RowMajor : ColMajor>, + (Dest::Flags&RowMajorBit) ? RowMajor : ColMajor, + Dest::InnerStrideAtCompileTime>, ActualLhsTypeCleaned, ActualRhsTypeCleaned, Dest, BlockingType> GemmFunctor; BlockingType blocking(dst.rows(), dst.cols(), lhs.cols(), 1, true); diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h index 5cd2794a..d68d2f96 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h @@ -25,51 +25,54 @@ namespace internal { **********************************************************************/ // forward declarations (defined at the end of this file) -template +template struct tribb_kernel; /* Optimized matrix-matrix product evaluating only one triangular half */ template + int ResStorageOrder, int ResInnerStride, int UpLo, int Version = Specialized> struct general_matrix_matrix_triangular_product; // as usual if the result is row major => we transpose the product template -struct general_matrix_matrix_triangular_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int UpLo, int Version> +struct general_matrix_matrix_triangular_product { typedef typename ScalarBinaryOpTraits::ReturnType ResScalar; static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* lhs, Index lhsStride, - const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resStride, + const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resIncr, Index resStride, const ResScalar& alpha, level3_blocking& blocking) { general_matrix_matrix_triangular_product - ::run(size,depth,rhs,rhsStride,lhs,lhsStride,res,resStride,alpha,blocking); + ColMajor, ResInnerStride, UpLo==Lower?Upper:Lower> + ::run(size,depth,rhs,rhsStride,lhs,lhsStride,res,resIncr,resStride,alpha,blocking); } }; template -struct general_matrix_matrix_triangular_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int UpLo, int Version> +struct general_matrix_matrix_triangular_product { typedef typename ScalarBinaryOpTraits::ReturnType ResScalar; static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* _lhs, Index lhsStride, - const RhsScalar* _rhs, Index rhsStride, ResScalar* _res, Index resStride, + const RhsScalar* _rhs, Index rhsStride, + ResScalar* _res, Index resIncr, Index resStride, const ResScalar& alpha, level3_blocking& blocking) { typedef gebp_traits Traits; typedef const_blas_data_mapper LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); Index mc = (std::min)(size,blocking.mc()); @@ -87,7 +90,7 @@ struct general_matrix_matrix_triangular_product pack_lhs; gemm_pack_rhs pack_rhs; gebp_kernel gebp; - tribb_kernel sybb; + tribb_kernel sybb; for(Index k2=0; k2 +template struct tribb_kernel { typedef gebp_traits Traits; @@ -142,13 +144,15 @@ struct tribb_kernel enum { BlockSize = meta_least_common_multiple::ret }; - void operator()(ResScalar* _res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, const ResScalar& alpha) + void operator()(ResScalar* _res, Index resIncr, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, const ResScalar& alpha) { - typedef blas_data_mapper ResMapper; - ResMapper res(_res, resStride); - gebp_kernel gebp_kernel; + typedef blas_data_mapper ResMapper; + typedef blas_data_mapper BufferMapper; + ResMapper res(_res, resStride, resIncr); + gebp_kernel gebp_kernel1; + gebp_kernel gebp_kernel2; - Matrix buffer; + Matrix buffer((internal::constructor_without_unaligned_array_assert())); // let's process the block per panel of actual_mc x BlockSize, // again, each is split into three parts, etc. @@ -158,31 +162,32 @@ struct tribb_kernel const RhsScalar* actual_b = blockB+j*depth; if(UpLo==Upper) - gebp_kernel(res.getSubMapper(0, j), blockA, actual_b, j, depth, actualBlockSize, alpha, - -1, -1, 0, 0); - + gebp_kernel1(res.getSubMapper(0, j), blockA, actual_b, j, depth, actualBlockSize, alpha, + -1, -1, 0, 0); + // selfadjoint micro block { Index i = j; buffer.setZero(); // 1 - apply the kernel on the temporary buffer - gebp_kernel(ResMapper(buffer.data(), BlockSize), blockA+depth*i, actual_b, actualBlockSize, depth, actualBlockSize, alpha, - -1, -1, 0, 0); + gebp_kernel2(BufferMapper(buffer.data(), BlockSize), blockA+depth*i, actual_b, actualBlockSize, depth, actualBlockSize, alpha, + -1, -1, 0, 0); + // 2 - triangular accumulation for(Index j1=0; j1 enum { IsRowMajor = (internal::traits::Flags&RowMajorBit) ? 1 : 0, LhsIsRowMajor = _ActualLhs::Flags&RowMajorBit ? 1 : 0, - RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0 + RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0, + SkipDiag = (UpLo&(UnitDiag|ZeroDiag))!=0 }; Index size = mat.cols(); + if(SkipDiag) + size--; Index depth = actualLhs.cols(); typedef internal::gemm_blocking_space internal::general_matrix_matrix_triangular_product + IsRowMajor ? RowMajor : ColMajor, MatrixType::InnerStrideAtCompileTime, UpLo&(Lower|Upper)> ::run(size, depth, - &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &actualRhs.coeffRef(0,0), actualRhs.outerStride(), - mat.data(), mat.outerStride(), actualAlpha, blocking); + &actualLhs.coeffRef(SkipDiag&&(UpLo&Lower)==Lower ? 1 : 0,0), actualLhs.outerStride(), + &actualRhs.coeffRef(0,SkipDiag&&(UpLo&Upper)==Upper ? 1 : 0), actualRhs.outerStride(), + mat.data() + (SkipDiag ? (bool(IsRowMajor) != ((UpLo&Lower)==Lower) ? mat.innerStride() : mat.outerStride() ) : 0), + mat.innerStride(), mat.outerStride(), actualAlpha, blocking); } }; @@ -294,6 +304,7 @@ template template TriangularView& TriangularViewImpl::_assignProduct(const ProductType& prod, const Scalar& alpha, bool beta) { + EIGEN_STATIC_ASSERT((UpLo&UnitDiag)==0, WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED); eigen_assert(derived().nestedExpression().rows() == prod.rows() && derived().cols() == prod.cols()); general_product_to_triangular_selector::InnerSize==1>::run(derived().nestedExpression().const_cast_derived(), prod, alpha, beta); diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h index 5b7c15cc..691f95d6 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h @@ -40,7 +40,7 @@ namespace internal { template struct general_matrix_matrix_rankupdate : general_matrix_matrix_triangular_product< - Index,Scalar,AStorageOrder,ConjugateA,Scalar,AStorageOrder,ConjugateA,ResStorageOrder,UpLo,BuiltIn> {}; + Index,Scalar,AStorageOrder,ConjugateA,Scalar,AStorageOrder,ConjugateA,ResStorageOrder,1,UpLo,BuiltIn> {}; // try to go to BLAS specialization @@ -48,19 +48,19 @@ struct general_matrix_matrix_rankupdate : template \ struct general_matrix_matrix_triangular_product { \ + Scalar,RhsStorageOrder,ConjugateRhs,ColMajor,1,UpLo,Specialized> { \ static EIGEN_STRONG_INLINE void run(Index size, Index depth,const Scalar* lhs, Index lhsStride, \ - const Scalar* rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha, level3_blocking& blocking) \ + const Scalar* rhs, Index rhsStride, Scalar* res, Index resIncr, Index resStride, Scalar alpha, level3_blocking& blocking) \ { \ - if (lhs==rhs) { \ + if ( lhs==rhs && ((UpLo&(Lower|Upper))==UpLo) ) { \ general_matrix_matrix_rankupdate \ ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha,blocking); \ } else { \ general_matrix_matrix_triangular_product \ - ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha,blocking); \ + ColMajor, 1, UpLo, BuiltIn> \ + ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resIncr,resStride,alpha,blocking); \ } \ } \ }; @@ -88,7 +88,7 @@ struct general_matrix_matrix_rankupdate(lhsStride), ldc=convert_index(resStride), n=convert_index(size), k=convert_index(depth); \ char uplo=((IsLower) ? 'L' : 'U'), trans=((AStorageOrder==RowMajor) ? 'T':'N'); \ EIGTYPE beta(1); \ - BLASFUNC(&uplo, &trans, &n, &k, &numext::real_ref(alpha), lhs, &lda, &numext::real_ref(beta), res, &ldc); \ + BLASFUNC(&uplo, &trans, &n, &k, (const BLASTYPE*)&numext::real_ref(alpha), lhs, &lda, (const BLASTYPE*)&numext::real_ref(beta), res, &ldc); \ } \ }; @@ -125,9 +125,13 @@ struct general_matrix_matrix_rankupdate \ -struct general_matrix_matrix_product \ +struct general_matrix_matrix_product \ { \ typedef gebp_traits Traits; \ \ static void run(Index rows, Index cols, Index depth, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, \ level3_blocking& /*blocking*/, \ GemmParallelInfo* /*info = 0*/) \ { \ using std::conj; \ \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char transa, transb; \ BlasIndex m, n, k, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -100,13 +102,20 @@ static void run(Index rows, Index cols, Index depth, \ ldb = convert_index(b_tmp.outerStride()); \ } else b = _rhs; \ \ - BLASPREFIX##gemm_(&transa, &transb, &m, &n, &k, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&transa, &transb, &m, &n, &k, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ }}; -GEMM_SPECIALIZATION(double, d, double, d) -GEMM_SPECIALIZATION(float, f, float, s) -GEMM_SPECIALIZATION(dcomplex, cd, double, z) -GEMM_SPECIALIZATION(scomplex, cf, float, c) +#ifdef EIGEN_USE_MKL +GEMM_SPECIALIZATION(double, d, double, dgemm) +GEMM_SPECIALIZATION(float, f, float, sgemm) +GEMM_SPECIALIZATION(dcomplex, cd, MKL_Complex16, zgemm) +GEMM_SPECIALIZATION(scomplex, cf, MKL_Complex8, cgemm) +#else +GEMM_SPECIALIZATION(double, d, double, dgemm_) +GEMM_SPECIALIZATION(float, f, float, sgemm_) +GEMM_SPECIALIZATION(dcomplex, cd, double, zgemm_) +GEMM_SPECIALIZATION(scomplex, cf, float, cgemm_) +#endif } // end namespase internal diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h index 3c1a7fc4..a597c1f4 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h @@ -183,8 +183,8 @@ EIGEN_DONT_INLINE void general_matrix_vector_product \ struct general_matrix_vector_product_gemv \ { \ @@ -113,14 +113,21 @@ static void run( \ x_ptr=x_tmp.data(); \ incx=1; \ } else x_ptr=rhs; \ - BLASPREFIX##gemv_(&trans, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, &numext::real_ref(beta), (BLASTYPE*)res, &incy); \ + BLASFUNC(&trans, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &incy); \ }\ }; -EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, d) -EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, s) -EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, double, z) -EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, float, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, dgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, sgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, MKL_Complex16, zgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, MKL_Complex8 , cgemv) +#else +EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, dgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, sgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, double, zgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, float, cgemv_) +#endif } // end namespase internal diff --git a/eigenlib/Eigen/src/Core/products/Parallelizer.h b/eigenlib/Eigen/src/Core/products/Parallelizer.h index 2a31e4cb..a3cc05b7 100644 --- a/eigenlib/Eigen/src/Core/products/Parallelizer.h +++ b/eigenlib/Eigen/src/Core/products/Parallelizer.h @@ -17,7 +17,8 @@ namespace internal { /** \internal */ inline void manage_multi_threading(Action action, int* v) { - static EIGEN_UNUSED int m_maxThreads = -1; + static int m_maxThreads = -1; + EIGEN_UNUSED_VARIABLE(m_maxThreads); if(action==SetAction) { @@ -75,7 +76,7 @@ template struct GemmParallelInfo { GemmParallelInfo() : sync(-1), users(0), lhs_start(0), lhs_length(0) {} - int volatile sync; + Index volatile sync; int volatile users; Index lhs_start; @@ -104,13 +105,14 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth, // - the sizes are large enough // compute the maximal number of threads from the size of the product: - // FIXME this has to be fine tuned + // This first heuristic takes into account that the product kernel is fully optimized when working with nr columns at once. Index size = transpose ? rows : cols; - Index pb_max_threads = std::max(1,size / 32); + Index pb_max_threads = std::max(1,size / Functor::Traits::nr); + // compute the maximal number of threads from the total amount of work: double work = static_cast(rows) * static_cast(cols) * static_cast(depth); - double kMinTaskSize = 50000; // Heuristic. + double kMinTaskSize = 50000; // FIXME improve this heuristic. pb_max_threads = std::max(1, std::min(pb_max_threads, work / kMinTaskSize)); // compute the number of threads we are going to use @@ -149,8 +151,10 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth, info[i].lhs_start = r0; info[i].lhs_length = actualBlockRows; - if(transpose) func(c0, actualBlockCols, 0, rows, info); - else func(0, rows, c0, actualBlockCols, info); + if(transpose) + func(c0, actualBlockCols, 0, rows, info); + else + func(0, rows, c0, actualBlockCols, info); } #endif } diff --git a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h index da6f82ab..04c93348 100644 --- a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +++ b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h @@ -277,20 +277,21 @@ struct symm_pack_rhs template + int ResStorageOrder, int ResInnerStride> struct product_selfadjoint_matrix; template -struct product_selfadjoint_matrix + int RhsStorageOrder, bool RhsSelfAdjoint, bool ConjugateRhs, + int ResInnerStride> +struct product_selfadjoint_matrix { static EIGEN_STRONG_INLINE void run( Index rows, Index cols, const Scalar* lhs, Index lhsStride, const Scalar* rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { product_selfadjoint_matrix::IsComplex && EIGEN_LOGICAL_XOR(RhsSelfAdjoint,ConjugateRhs), EIGEN_LOGICAL_XOR(LhsSelfAdjoint,LhsStorageOrder==RowMajor) ? ColMajor : RowMajor, LhsSelfAdjoint, NumTraits::IsComplex && EIGEN_LOGICAL_XOR(LhsSelfAdjoint,ConjugateLhs), - ColMajor> - ::run(cols, rows, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha, blocking); + ColMajor,ResInnerStride> + ::run(cols, rows, rhs, rhsStride, lhs, lhsStride, res, resIncr, resStride, alpha, blocking); } }; template -struct product_selfadjoint_matrix + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct product_selfadjoint_matrix { static EIGEN_DONT_INLINE void run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking); }; template -EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { Index size = rows; @@ -334,11 +337,11 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix LhsMapper; typedef const_blas_data_mapper LhsTransposeMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); LhsTransposeMapper lhs_transpose(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -398,26 +401,28 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix -struct product_selfadjoint_matrix + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct product_selfadjoint_matrix { static EIGEN_DONT_INLINE void run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking); }; template -EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { Index size = cols; @@ -425,9 +430,9 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix Traits; typedef const_blas_data_mapper LhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); - ResMapper res(_res,resStride); + ResMapper res(_res,resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -503,12 +508,13 @@ struct selfadjoint_product_impl NumTraits::IsComplex && EIGEN_LOGICAL_XOR(LhsIsUpper,bool(LhsBlasTraits::NeedToConjugate)), EIGEN_LOGICAL_XOR(RhsIsUpper,internal::traits::Flags &RowMajorBit) ? RowMajor : ColMajor, RhsIsSelfAdjoint, NumTraits::IsComplex && EIGEN_LOGICAL_XOR(RhsIsUpper,bool(RhsBlasTraits::NeedToConjugate)), - internal::traits::Flags&RowMajorBit ? RowMajor : ColMajor> + internal::traits::Flags&RowMajorBit ? RowMajor : ColMajor, + Dest::InnerStrideAtCompileTime> ::run( lhs.rows(), rhs.cols(), // sizes &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info - &dst.coeffRef(0,0), dst.outerStride(), // result info + &dst.coeffRef(0,0), dst.innerStride(), dst.outerStride(), // result info actualAlpha, blocking // alpha ); } diff --git a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h index a45238d6..61396dbd 100644 --- a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h @@ -40,20 +40,22 @@ namespace internal { /* Optimized selfadjoint matrix * matrix (?SYMM/?HEMM) product */ -#define EIGEN_BLAS_SYMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_SYMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ \ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='L', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -81,25 +83,27 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } else b = _rhs; \ \ - BLASPREFIX##symm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -#define EIGEN_BLAS_HEMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_HEMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='L', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -144,33 +148,41 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } \ \ - BLASPREFIX##hemm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -EIGEN_BLAS_SYMM_L(double, double, d, d) -EIGEN_BLAS_SYMM_L(float, float, f, s) -EIGEN_BLAS_HEMM_L(dcomplex, double, cd, z) -EIGEN_BLAS_HEMM_L(scomplex, float, cf, c) - +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_SYMM_L(double, double, d, dsymm) +EIGEN_BLAS_SYMM_L(float, float, f, ssymm) +EIGEN_BLAS_HEMM_L(dcomplex, MKL_Complex16, cd, zhemm) +EIGEN_BLAS_HEMM_L(scomplex, MKL_Complex8, cf, chemm) +#else +EIGEN_BLAS_SYMM_L(double, double, d, dsymm_) +EIGEN_BLAS_SYMM_L(float, float, f, ssymm_) +EIGEN_BLAS_HEMM_L(dcomplex, double, cd, zhemm_) +EIGEN_BLAS_HEMM_L(scomplex, float, cf, chemm_) +#endif /* Optimized matrix * selfadjoint matrix (?SYMM/?HEMM) product */ -#define EIGEN_BLAS_SYMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_SYMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ \ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='R', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -197,25 +209,27 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } else b = _lhs; \ \ - BLASPREFIX##symm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -#define EIGEN_BLAS_HEMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_HEMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='R', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -259,15 +273,21 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } \ \ - BLASPREFIX##hemm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ } \ }; -EIGEN_BLAS_SYMM_R(double, double, d, d) -EIGEN_BLAS_SYMM_R(float, float, f, s) -EIGEN_BLAS_HEMM_R(dcomplex, double, cd, z) -EIGEN_BLAS_HEMM_R(scomplex, float, cf, c) - +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_SYMM_R(double, double, d, dsymm) +EIGEN_BLAS_SYMM_R(float, float, f, ssymm) +EIGEN_BLAS_HEMM_R(dcomplex, MKL_Complex16, cd, zhemm) +EIGEN_BLAS_HEMM_R(scomplex, MKL_Complex8, cf, chemm) +#else +EIGEN_BLAS_SYMM_R(double, double, d, dsymm_) +EIGEN_BLAS_SYMM_R(float, float, f, ssymm_) +EIGEN_BLAS_HEMM_R(dcomplex, double, cd, zhemm_) +EIGEN_BLAS_HEMM_R(scomplex, float, cf, chemm_) +#endif } // end namespace internal } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h index d97f8caa..3fd180e6 100644 --- a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h +++ b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h @@ -83,10 +83,10 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product(t3); - size_t starti = FirstTriangular ? 0 : j+2; - size_t endi = FirstTriangular ? j : size; - size_t alignedStart = (starti) + internal::first_default_aligned(&res[starti], endi-starti); - size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize); + Index starti = FirstTriangular ? 0 : j+2; + Index endi = FirstTriangular ? j : size; + Index alignedStart = (starti) + internal::first_default_aligned(&res[starti], endi-starti); + Index alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize); res[j] += cjd.pmul(numext::real(A0[j]), t0); res[j+1] += cjd.pmul(numext::real(A1[j+1]), t1); @@ -101,7 +101,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product(a0It); a0It += PacketSize; Packet A1i = ploadu(a1It); a1It += PacketSize; @@ -125,7 +125,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product internal::general_matrix_matrix_triangular_product::IsComplex, Scalar, OtherIsRowMajor ? ColMajor : RowMajor, (!OtherBlasTraits::NeedToConjugate) && NumTraits::IsComplex, - IsRowMajor ? RowMajor : ColMajor, UpLo> + IsRowMajor ? RowMajor : ColMajor, MatrixType::InnerStrideAtCompileTime, UpLo> ::run(size, depth, &actualOther.coeffRef(0,0), actualOther.outerStride(), &actualOther.coeffRef(0,0), actualOther.outerStride(), - mat.data(), mat.outerStride(), actualAlpha, blocking); + mat.data(), mat.innerStride(), mat.outerStride(), actualAlpha, blocking); } }; diff --git a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h index 8a2f7cd7..2fb408d1 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h +++ b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h @@ -45,22 +45,24 @@ template + int ResStorageOrder, int ResInnerStride, + int Version = Specialized> struct product_triangular_matrix_matrix; template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,RowMajor,ResInnerStride,Version> { static EIGEN_STRONG_INLINE void run( Index rows, Index cols, Index depth, const Scalar* lhs, Index lhsStride, const Scalar* rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { product_triangular_matrix_matrix - ::run(cols, rows, depth, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha, blocking); + ColMajor, ResInnerStride> + ::run(cols, rows, depth, rhs, rhsStride, lhs, lhsStride, res, resIncr, resStride, alpha, blocking); } }; // implements col-major += alpha * op(triangular) * op(general) template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version> { typedef gebp_traits Traits; @@ -95,20 +98,21 @@ struct product_triangular_matrix_matrix& blocking); }; template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> EIGEN_DONT_INLINE void product_triangular_matrix_matrix::run( + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version>::run( Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { // strip zeros @@ -119,10 +123,10 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -137,7 +141,13 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix triangularBuffer; + // To work around an "error: member reference base type 'Matrix<...> + // (Eigen::internal::constructor_without_unaligned_array_assert (*)())' is + // not a structure or union" compilation error in nvcc (tested V8.0.61), + // create a dummy internal::constructor_without_unaligned_array_assert + // object to pass to the Matrix constructor. + internal::constructor_without_unaligned_array_assert a; + Matrix triangularBuffer(a); triangularBuffer.setZero(); if((Mode&ZeroDiag)==ZeroDiag) triangularBuffer.diagonal().setZero(); @@ -229,10 +239,11 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version> { typedef gebp_traits Traits; enum { @@ -245,20 +256,21 @@ struct product_triangular_matrix_matrix& blocking); }; template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> EIGEN_DONT_INLINE void product_triangular_matrix_matrix::run( + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version>::run( Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { const Index PacketBytes = packet_traits::size*sizeof(Scalar); @@ -270,10 +282,10 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -284,7 +296,8 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix triangularBuffer; + internal::constructor_without_unaligned_array_assert a; + Matrix triangularBuffer(a); triangularBuffer.setZero(); if((Mode&ZeroDiag)==ZeroDiag) triangularBuffer.diagonal().setZero(); @@ -393,7 +406,9 @@ struct triangular_product_impl { template static void run(Dest& dst, const Lhs &a_lhs, const Rhs &a_rhs, const typename Dest::Scalar& alpha) { - typedef typename Dest::Scalar Scalar; + typedef typename Lhs::Scalar LhsScalar; + typedef typename Rhs::Scalar RhsScalar; + typedef typename Dest::Scalar Scalar; typedef internal::blas_traits LhsBlasTraits; typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType; @@ -405,8 +420,9 @@ struct triangular_product_impl typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(a_lhs); typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(a_rhs); - Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(a_lhs) - * RhsBlasTraits::extractScalarFactor(a_rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(a_lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(a_rhs); + Scalar actualAlpha = alpha * lhs_alpha * rhs_alpha; typedef internal::gemm_blocking_space<(Dest::Flags&RowMajorBit) ? RowMajor : ColMajor,Scalar,Scalar, Lhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, Lhs::MaxColsAtCompileTime,4> BlockingType; @@ -423,14 +439,29 @@ struct triangular_product_impl Mode, LhsIsTriangular, (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate, (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate, - (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor> + (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor, Dest::InnerStrideAtCompileTime> ::run( stripedRows, stripedCols, stripedDepth, // sizes &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info - &dst.coeffRef(0,0), dst.outerStride(), // result info + &dst.coeffRef(0,0), dst.innerStride(), dst.outerStride(), // result info actualAlpha, blocking ); + + // Apply correction if the diagonal is unit and a scalar factor was nested: + if ((Mode&UnitDiag)==UnitDiag) + { + if (LhsIsTriangular && lhs_alpha!=LhsScalar(1)) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dst.topRows(diagSize) -= ((lhs_alpha-LhsScalar(1))*a_rhs).topRows(diagSize); + } + else if ((!LhsIsTriangular) && rhs_alpha!=RhsScalar(1)) + { + Index diagSize = (std::min)(rhs.rows(),rhs.cols()); + dst.leftCols(diagSize) -= (rhs_alpha-RhsScalar(1))*a_lhs.leftCols(diagSize); + } + } } }; diff --git a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h index aecded6b..a98d12e4 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h @@ -46,7 +46,7 @@ template {}; + RhsStorageOrder, ConjugateRhs, ResStorageOrder, 1, BuiltIn> {}; // try to go to BLAS specialization @@ -55,13 +55,15 @@ template \ struct product_triangular_matrix_matrix { \ + LhsStorageOrder,ConjugateLhs, RhsStorageOrder,ConjugateRhs,ColMajor,1,Specialized> { \ static inline void run(Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride,\ - const Scalar* _rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha, level3_blocking& blocking) { \ + const Scalar* _rhs, Index rhsStride, Scalar* res, Index resIncr, Index resStride, Scalar alpha, level3_blocking& blocking) { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ product_triangular_matrix_matrix_trmm::run( \ - _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ } \ }; @@ -75,7 +77,7 @@ EIGEN_BLAS_TRMM_SPECIALIZE(scomplex, true) EIGEN_BLAS_TRMM_SPECIALIZE(scomplex, false) // implements col-major += alpha * op(triangular) * op(general) -#define EIGEN_BLAS_TRMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ @@ -115,8 +117,8 @@ struct product_triangular_matrix_matrix_trmm::run( \ - _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ + LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, 1, BuiltIn>::run( \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, 1, resStride, alpha, blocking); \ /*std::cout << "TRMM_L: A is not square! Go to Eigen TRMM implementation!\n";*/ \ } else { \ /* Make sense to call GEMM */ \ @@ -124,8 +126,8 @@ struct product_triangular_matrix_matrix_trmm(); \ BlasIndex aStride = convert_index(aa_tmp.outerStride()); \ gemm_blocking_space gemm_blocking(_rows,_cols,_depth, 1, true); \ - general_matrix_matrix_product::run( \ - rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, resStride, alpha, gemm_blocking, 0); \ + general_matrix_matrix_product::run( \ + rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, 1, resStride, alpha, gemm_blocking, 0); \ \ /*std::cout << "TRMM_L: A is not square! Go to BLAS GEMM implementation! " << nthr<<" \n";*/ \ } \ @@ -172,7 +174,7 @@ struct product_triangular_matrix_matrix_trmm > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ @@ -180,13 +182,20 @@ struct product_triangular_matrix_matrix_trmm \ @@ -225,8 +234,8 @@ struct product_triangular_matrix_matrix_trmm::run( \ - _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ + LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, 1, BuiltIn>::run( \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, 1, resStride, alpha, blocking); \ /*std::cout << "TRMM_R: A is not square! Go to Eigen TRMM implementation!\n";*/ \ } else { \ /* Make sense to call GEMM */ \ @@ -234,8 +243,8 @@ struct product_triangular_matrix_matrix_trmm(); \ BlasIndex aStride = convert_index(aa_tmp.outerStride()); \ gemm_blocking_space gemm_blocking(_rows,_cols,_depth, 1, true); \ - general_matrix_matrix_product::run( \ - rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, resStride, alpha, gemm_blocking, 0); \ + general_matrix_matrix_product::run( \ + rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, 1, resStride, alpha, gemm_blocking, 0); \ \ /*std::cout << "TRMM_R: A is not square! Go to BLAS GEMM implementation! " << nthr<<" \n";*/ \ } \ @@ -282,7 +291,7 @@ struct product_triangular_matrix_matrix_trmm > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ @@ -290,11 +299,17 @@ struct product_triangular_matrix_matrix_trmm struct trmv_selector typename internal::add_const_on_value_type::type actualLhs = LhsBlasTraits::extract(lhs); typename internal::add_const_on_value_type::type actualRhs = RhsBlasTraits::extract(rhs); - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs) - * RhsBlasTraits::extractScalarFactor(rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(rhs); + ResScalar actualAlpha = alpha * lhs_alpha * rhs_alpha; enum { // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 @@ -274,6 +275,12 @@ template struct trmv_selector else dest = MappedDest(actualDestPtr, dest.size()); } + + if ( ((Mode&UnitDiag)==UnitDiag) && (lhs_alpha!=LhsScalar(1)) ) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dest.head(diagSize) -= (lhs_alpha-LhsScalar(1))*rhs.head(diagSize); + } } }; @@ -295,8 +302,9 @@ template struct trmv_selector typename add_const::type actualLhs = LhsBlasTraits::extract(lhs); typename add_const::type actualRhs = RhsBlasTraits::extract(rhs); - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs) - * RhsBlasTraits::extractScalarFactor(rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(rhs); + ResScalar actualAlpha = alpha * lhs_alpha * rhs_alpha; enum { DirectlyUseRhs = ActualRhsTypeCleaned::InnerStrideAtCompileTime==1 @@ -326,6 +334,12 @@ template struct trmv_selector actualRhsPtr,1, dest.data(),dest.innerStride(), actualAlpha); + + if ( ((Mode&UnitDiag)==UnitDiag) && (lhs_alpha!=LhsScalar(1)) ) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dest.head(diagSize) -= (lhs_alpha-LhsScalar(1))*rhs.head(diagSize); + } } }; diff --git a/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h b/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h index 07bf26ce..3d47a2b9 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h @@ -71,7 +71,7 @@ EIGEN_BLAS_TRMV_SPECIALIZE(dcomplex) EIGEN_BLAS_TRMV_SPECIALIZE(scomplex) // implements col-major: res += alpha * op(triangular) * vector -#define EIGEN_BLAS_TRMV_CM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMV_CM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX, BLASPOSTFIX) \ template \ struct triangular_matrix_vector_product_trmv { \ enum { \ @@ -121,10 +121,10 @@ struct triangular_matrix_vector_product_trmv(size); \ n = convert_index(cols-size); \ } \ - BLASPREFIX##gemv_(&trans, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, &numext::real_ref(beta), (BLASTYPE*)y, &incy); \ + BLASPREFIX##gemv##BLASPOSTFIX(&trans, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)y, &incy); \ } \ } \ }; -EIGEN_BLAS_TRMV_CM(double, double, d, d) -EIGEN_BLAS_TRMV_CM(dcomplex, double, cd, z) -EIGEN_BLAS_TRMV_CM(float, float, f, s) -EIGEN_BLAS_TRMV_CM(scomplex, float, cf, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_TRMV_CM(double, double, d, d,) +EIGEN_BLAS_TRMV_CM(dcomplex, MKL_Complex16, cd, z,) +EIGEN_BLAS_TRMV_CM(float, float, f, s,) +EIGEN_BLAS_TRMV_CM(scomplex, MKL_Complex8, cf, c,) +#else +EIGEN_BLAS_TRMV_CM(double, double, d, d, _) +EIGEN_BLAS_TRMV_CM(dcomplex, double, cd, z, _) +EIGEN_BLAS_TRMV_CM(float, float, f, s, _) +EIGEN_BLAS_TRMV_CM(scomplex, float, cf, c, _) +#endif // implements row-major: res += alpha * op(triangular) * vector -#define EIGEN_BLAS_TRMV_RM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMV_RM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX, BLASPOSTFIX) \ template \ struct triangular_matrix_vector_product_trmv { \ enum { \ @@ -203,10 +210,10 @@ struct triangular_matrix_vector_product_trmv(size); \ n = convert_index(cols-size); \ } \ - BLASPREFIX##gemv_(&trans, &n, &m, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, &numext::real_ref(beta), (BLASTYPE*)y, &incy); \ + BLASPREFIX##gemv##BLASPOSTFIX(&trans, &n, &m, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)y, &incy); \ } \ } \ }; -EIGEN_BLAS_TRMV_RM(double, double, d, d) -EIGEN_BLAS_TRMV_RM(dcomplex, double, cd, z) -EIGEN_BLAS_TRMV_RM(float, float, f, s) -EIGEN_BLAS_TRMV_RM(scomplex, float, cf, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_TRMV_RM(double, double, d, d,) +EIGEN_BLAS_TRMV_RM(dcomplex, MKL_Complex16, cd, z,) +EIGEN_BLAS_TRMV_RM(float, float, f, s,) +EIGEN_BLAS_TRMV_RM(scomplex, MKL_Complex8, cf, c,) +#else +EIGEN_BLAS_TRMV_RM(double, double, d, d,_) +EIGEN_BLAS_TRMV_RM(dcomplex, double, cd, z,_) +EIGEN_BLAS_TRMV_RM(float, float, f, s,_) +EIGEN_BLAS_TRMV_RM(scomplex, float, cf, c,_) +#endif } // end namespase internal diff --git a/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h b/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h index 223c38b8..e3ed2cd1 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h +++ b/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h @@ -15,48 +15,48 @@ namespace Eigen { namespace internal { // if the rhs is row major, let's transpose the product -template -struct triangular_solve_matrix +template +struct triangular_solve_matrix { static void run( Index size, Index cols, const Scalar* tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking) { triangular_solve_matrix< Scalar, Index, Side==OnTheLeft?OnTheRight:OnTheLeft, (Mode&UnitDiag) | ((Mode&Upper) ? Lower : Upper), NumTraits::IsComplex && Conjugate, - TriStorageOrder==RowMajor ? ColMajor : RowMajor, ColMajor> - ::run(size, cols, tri, triStride, _other, otherStride, blocking); + TriStorageOrder==RowMajor ? ColMajor : RowMajor, ColMajor, OtherInnerStride> + ::run(size, cols, tri, triStride, _other, otherIncr, otherStride, blocking); } }; /* Optimized triangular solver with multiple right hand side and the triangular matrix on the left */ -template -struct triangular_solve_matrix +template +struct triangular_solve_matrix { static EIGEN_DONT_INLINE void run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking); }; -template -EIGEN_DONT_INLINE void triangular_solve_matrix::run( +template +EIGEN_DONT_INLINE void triangular_solve_matrix::run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking) { Index cols = otherSize; typedef const_blas_data_mapper TriMapper; - typedef blas_data_mapper OtherMapper; + typedef blas_data_mapper OtherMapper; TriMapper tri(_tri, triStride); - OtherMapper other(_other, otherStride); + OtherMapper other(_other, otherStride, otherIncr); typedef gebp_traits Traits; @@ -128,19 +128,19 @@ EIGEN_DONT_INLINE void triangular_solve_matrix -struct triangular_solve_matrix +template +struct triangular_solve_matrix { static EIGEN_DONT_INLINE void run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking); }; -template -EIGEN_DONT_INLINE void triangular_solve_matrix::run( +template +EIGEN_DONT_INLINE void triangular_solve_matrix::run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking) { Index rows = otherSize; typedef typename NumTraits::Real RealScalar; - typedef blas_data_mapper LhsMapper; + typedef blas_data_mapper LhsMapper; typedef const_blas_data_mapper RhsMapper; - LhsMapper lhs(_other, otherStride); + LhsMapper lhs(_other, otherStride, otherIncr); RhsMapper rhs(_tri, triStride); typedef gebp_traits Traits; @@ -297,24 +297,24 @@ EIGEN_DONT_INLINE void triangular_solve_matrix \ -struct triangular_solve_matrix \ +struct triangular_solve_matrix \ { \ enum { \ IsLower = (Mode&Lower) == Lower, \ @@ -51,8 +51,10 @@ struct triangular_solve_matrix& /*blocking*/) \ + EIGTYPE* _other, Index otherIncr, Index otherStride, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(otherIncr); \ + eigen_assert(otherIncr == 1); \ BlasIndex m = convert_index(size), n = convert_index(otherSize), lda, ldb; \ char side = 'L', uplo, diag='N', transa; \ /* Set alpha_ */ \ @@ -80,20 +82,26 @@ struct triangular_solve_matrix \ -struct triangular_solve_matrix \ +struct triangular_solve_matrix \ { \ enum { \ IsLower = (Mode&Lower) == Lower, \ @@ -104,8 +112,10 @@ struct triangular_solve_matrix& /*blocking*/) \ + EIGTYPE* _other, Index otherIncr, Index otherStride, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(otherIncr); \ + eigen_assert(otherIncr == 1); \ BlasIndex m = convert_index(otherSize), n = convert_index(size), lda, ldb; \ char side = 'R', uplo, diag='N', transa; \ /* Set alpha_ */ \ @@ -133,16 +143,22 @@ struct triangular_solve_matrix + int ResStorageOrder, int ResInnerStride> struct general_matrix_matrix_product; template +class BlasLinearMapper; + template -class BlasLinearMapper { +class BlasLinearMapper { public: typedef typename packet_traits::type Packet; typedef typename packet_traits::half HalfPacket; - EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data) : m_data(data) {} + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data, Index incr=1) + : m_data(data) + { + EIGEN_ONLY_USED_FOR_DEBUG(incr); + eigen_assert(incr==1); + } EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void prefetch(int i) const { internal::prefetch(&operator()(i)); @@ -188,16 +196,25 @@ class BlasLinearMapper { }; // Lightweight helper class to access matrix coefficients. -template -class blas_data_mapper { - public: +template +class blas_data_mapper; + +template +class blas_data_mapper +{ +public: typedef typename packet_traits::type Packet; typedef typename packet_traits::half HalfPacket; typedef BlasLinearMapper LinearMapper; typedef BlasVectorMapper VectorMapper; - EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride) : m_data(data), m_stride(stride) {} + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr=1) + : m_data(data), m_stride(stride) + { + EIGEN_ONLY_USED_FOR_DEBUG(incr); + eigen_assert(incr==1); + } EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper getSubMapper(Index i, Index j) const { @@ -251,6 +268,90 @@ class blas_data_mapper { const Index m_stride; }; +// Implementation of non-natural increment (i.e. inner-stride != 1) +// The exposed API is not complete yet compared to the Incr==1 case +// because some features makes less sense in this case. +template +class BlasLinearMapper +{ +public: + typedef typename packet_traits::type Packet; + typedef typename packet_traits::half HalfPacket; + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data,Index incr) : m_data(data), m_incr(incr) {} + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void prefetch(int i) const { + internal::prefetch(&operator()(i)); + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i) const { + return m_data[i*m_incr.value()]; + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet loadPacket(Index i) const { + return pgather(m_data + i*m_incr.value(), m_incr.value()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacket(Index i, const PacketType &p) const { + pscatter(m_data + i*m_incr.value(), p, m_incr.value()); + } + +protected: + Scalar *m_data; + const internal::variable_if_dynamic m_incr; +}; + +template +class blas_data_mapper +{ +public: + typedef typename packet_traits::type Packet; + typedef typename packet_traits::half HalfPacket; + + typedef BlasLinearMapper LinearMapper; + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr) : m_data(data), m_stride(stride), m_incr(incr) {} + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper + getSubMapper(Index i, Index j) const { + return blas_data_mapper(&operator()(i, j), m_stride, m_incr.value()); + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LinearMapper getLinearMapper(Index i, Index j) const { + return LinearMapper(&operator()(i, j), m_incr.value()); + } + + EIGEN_DEVICE_FUNC + EIGEN_ALWAYS_INLINE Scalar& operator()(Index i, Index j) const { + return m_data[StorageOrder==RowMajor ? j*m_incr.value() + i*m_stride : i*m_incr.value() + j*m_stride]; + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet loadPacket(Index i, Index j) const { + return pgather(&operator()(i, j),m_incr.value()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketT load(Index i, Index j) const { + return pgather(&operator()(i, j),m_incr.value()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void scatterPacket(Index i, Index j, const SubPacket &p) const { + pscatter(&operator()(i, j), p, m_stride); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubPacket gatherPacket(Index i, Index j) const { + return pgather(&operator()(i, j), m_stride); + } + +protected: + Scalar* EIGEN_RESTRICT m_data; + const Index m_stride; + const internal::variable_if_dynamic m_incr; +}; + // lightweight helper class to access matrix coefficients (const version) template class const_blas_data_mapper : public blas_data_mapper { diff --git a/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h b/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h index 7559e129..74f74cc4 100755 --- a/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h +++ b/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h @@ -43,13 +43,24 @@ #endif #pragma clang diagnostic ignored "-Wconstant-logical-operand" -#elif defined __GNUC__ && __GNUC__>=6 +#elif defined __GNUC__ - #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS + #if (!defined(EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS)) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) #pragma GCC diagnostic push #endif - #pragma GCC diagnostic ignored "-Wignored-attributes" - + // g++ warns about local variables shadowing member functions, which is too strict + #pragma GCC diagnostic ignored "-Wshadow" + #if __GNUC__ == 4 && __GNUC_MINOR__ < 8 + // Until g++-4.7 there are warnings when comparing unsigned int vs 0, even in templated functions: + #pragma GCC diagnostic ignored "-Wtype-limits" + #endif + #if __GNUC__>=6 + #pragma GCC diagnostic ignored "-Wignored-attributes" + #endif + #if __GNUC__==7 + // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89325 + #pragma GCC diagnostic ignored "-Wattributes" + #endif #endif #if defined __NVCC__ @@ -72,4 +83,12 @@ #pragma diag_suppress 2737 #endif +#else +// warnings already disabled: +# ifndef EIGEN_WARNINGS_DISABLED_2 +# define EIGEN_WARNINGS_DISABLED_2 +# elif defined(EIGEN_INTERNAL_DEBUGGING) +# error "Do not include \"DisableStupidWarnings.h\" recursively more than twice!" +# endif + #endif // not EIGEN_WARNINGS_DISABLED diff --git a/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h b/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h index ea107393..134544f9 100644 --- a/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h +++ b/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h @@ -47,11 +47,7 @@ template struct NumTraits; template struct EigenBase; template class DenseBase; template class PlainObjectBase; - - -template::value > -class DenseCoeffsBase; +template class DenseCoeffsBase; template /*Check IMKL version for compatibility: < 10.3 is not usable with Eigen*/ @@ -108,6 +109,10 @@ #endif #endif +#if defined(EIGEN_USE_BLAS) && !defined(EIGEN_USE_MKL) +#include "../../misc/blas.h" +#endif + namespace Eigen { typedef std::complex dcomplex; @@ -121,8 +126,5 @@ typedef int BlasIndex; } // end namespace Eigen -#if defined(EIGEN_USE_BLAS) -#include "../../misc/blas.h" -#endif #endif // EIGEN_MKL_SUPPORT_H diff --git a/eigenlib/Eigen/src/Core/util/Macros.h b/eigenlib/Eigen/src/Core/util/Macros.h index ace330b3..6b0399eb 100644 --- a/eigenlib/Eigen/src/Core/util/Macros.h +++ b/eigenlib/Eigen/src/Core/util/Macros.h @@ -13,7 +13,7 @@ #define EIGEN_WORLD_VERSION 3 #define EIGEN_MAJOR_VERSION 3 -#define EIGEN_MINOR_VERSION 2 +#define EIGEN_MINOR_VERSION 9 #define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ @@ -80,8 +80,8 @@ // 2015 14 1900 // "15" 15 1900 -/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC -#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC) +/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC or clang-cl +#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC || EIGEN_COMP_LLVM || EIGEN_COMP_CLANG) #define EIGEN_COMP_MSVC_STRICT _MSC_VER #else #define EIGEN_COMP_MSVC_STRICT 0 @@ -380,7 +380,8 @@ #if EIGEN_MAX_CPP_VER>=11 && \ ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)) \ || (defined(__GNUC__) && defined(_GLIBCXX_USE_C99)) \ - || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER))) + || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) \ + || (EIGEN_COMP_MSVC >= 1900) ) #define EIGEN_HAS_C99_MATH 1 #else #define EIGEN_HAS_C99_MATH 0 @@ -396,10 +397,24 @@ #endif #endif +// Does the compiler support type_traits? +// - full support of type traits was added only to GCC 5.1.0. +// - 20150626 corresponds to the last release of 4.x libstdc++ +#ifndef EIGEN_HAS_TYPE_TRAITS +#if EIGEN_MAX_CPP_VER>=11 && (EIGEN_HAS_CXX11 || EIGEN_COMP_MSVC >= 1700) \ + && ((!EIGEN_COMP_GNUC_STRICT) || EIGEN_GNUC_AT_LEAST(5, 1)) \ + && ((!defined(__GLIBCXX__)) || __GLIBCXX__ > 20150626) +#define EIGEN_HAS_TYPE_TRAITS 1 +#define EIGEN_INCLUDE_TYPE_TRAITS +#else +#define EIGEN_HAS_TYPE_TRAITS 0 +#endif +#endif + // Does the compiler support variadic templates? #ifndef EIGEN_HAS_VARIADIC_TEMPLATES #if EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) \ - && ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000) ) + && (!defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (EIGEN_CUDACC_VER >= 80000) ) // ^^ Disable the use of variadic templates when compiling with versions of nvcc older than 8.0 on ARM devices: // this prevents nvcc from crashing when compiling Eigen on Tegra X1 #define EIGEN_HAS_VARIADIC_TEMPLATES 1 @@ -413,7 +428,7 @@ #ifdef __CUDACC__ // Const expressions are supported provided that c++11 is enabled and we're using either clang or nvcc 7.5 or above -#if EIGEN_MAX_CPP_VER>=14 && (__cplusplus > 199711L && defined(__CUDACC_VER__) && (EIGEN_COMP_CLANG || __CUDACC_VER__ >= 70500)) +#if EIGEN_MAX_CPP_VER>=14 && (__cplusplus > 199711L && (EIGEN_COMP_CLANG || EIGEN_CUDACC_VER >= 70500)) #define EIGEN_HAS_CONSTEXPR 1 #endif #elif EIGEN_MAX_CPP_VER>=14 && (__has_feature(cxx_relaxed_constexpr) || (defined(__cplusplus) && __cplusplus >= 201402L) || \ @@ -487,11 +502,13 @@ // EIGEN_STRONG_INLINE is a stronger version of the inline, using __forceinline on MSVC, // but it still doesn't use GCC's always_inline. This is useful in (common) situations where MSVC needs forceinline // but GCC is still doing fine with just inline. +#ifndef EIGEN_STRONG_INLINE #if EIGEN_COMP_MSVC || EIGEN_COMP_ICC #define EIGEN_STRONG_INLINE __forceinline #else #define EIGEN_STRONG_INLINE inline #endif +#endif // EIGEN_ALWAYS_INLINE is the stronget, it has the effect of making the function inline and adding every possible // attribute to maximize inlining. This should only be used when really necessary: in particular, @@ -812,7 +829,8 @@ namespace Eigen { // just an empty macro ! #define EIGEN_EMPTY -#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || __CUDACC_VER__) // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324) +#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || EIGEN_CUDACC_VER>0) + // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324) #define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \ using Base::operator =; #elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653) @@ -832,11 +850,48 @@ namespace Eigen { #endif +/** + * \internal + * \brief Macro to explicitly define the default copy constructor. + * This is necessary, because the implicit definition is deprecated if the copy-assignment is overridden. + */ +#if EIGEN_HAS_CXX11 +#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS) EIGEN_DEVICE_FUNC CLASS(const CLASS&) = default; +#else +#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS) +#endif + + + /** \internal * \brief Macro to manually inherit assignment operators. * This is necessary, because the implicitly defined assignment operator gets deleted when a custom operator= is defined. + * With C++11 or later this also default-implements the copy-constructor */ -#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) +#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \ + EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \ + EIGEN_DEFAULT_COPY_CONSTRUCTOR(Derived) + +/** \internal + * \brief Macro to manually define default constructors and destructors. + * This is necessary when the copy constructor is re-defined. + * For empty helper classes this should usually be protected, to avoid accidentally creating empty objects. + * + * Hiding the default destructor lead to problems in C++03 mode together with boost::multiprecision + */ +#if EIGEN_HAS_CXX11 +#define EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(Derived) \ + EIGEN_DEVICE_FUNC Derived() = default; \ + EIGEN_DEVICE_FUNC ~Derived() = default; +#else +#define EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(Derived) \ + EIGEN_DEVICE_FUNC Derived() {}; \ + /* EIGEN_DEVICE_FUNC ~Derived() {}; */ +#endif + + + + /** * Just a side note. Commenting within defines works only by documenting @@ -986,7 +1041,13 @@ namespace Eigen { # define EIGEN_NOEXCEPT # define EIGEN_NOEXCEPT_IF(x) # define EIGEN_NO_THROW throw() -# define EIGEN_EXCEPTION_SPEC(X) throw(X) +# if EIGEN_COMP_MSVC + // MSVC does not support exception specifications (warning C4290), + // and they are deprecated in c++11 anyway. +# define EIGEN_EXCEPTION_SPEC(X) throw() +# else +# define EIGEN_EXCEPTION_SPEC(X) throw(X) +# endif #endif #endif // EIGEN_MACROS_H diff --git a/eigenlib/Eigen/src/Core/util/Memory.h b/eigenlib/Eigen/src/Core/util/Memory.h index 67053db6..291383c5 100644 --- a/eigenlib/Eigen/src/Core/util/Memory.h +++ b/eigenlib/Eigen/src/Core/util/Memory.h @@ -70,7 +70,7 @@ inline void throw_std_bad_alloc() throw std::bad_alloc(); #else std::size_t huge = static_cast(-1); - new int[huge]; + ::operator new(huge); #endif } @@ -150,7 +150,7 @@ EIGEN_DEVICE_FUNC inline void check_that_malloc_is_allowed() /** \internal Allocates \a size bytes. The returned pointer is guaranteed to have 16 or 32 bytes alignment depending on the requirements. * On allocation error, the returned pointer is null, and std::bad_alloc is thrown. */ -EIGEN_DEVICE_FUNC inline void* aligned_malloc(size_t size) +EIGEN_DEVICE_FUNC inline void* aligned_malloc(std::size_t size) { check_that_malloc_is_allowed(); @@ -185,7 +185,7 @@ EIGEN_DEVICE_FUNC inline void aligned_free(void *ptr) * \brief Reallocates an aligned block of memory. * \throws std::bad_alloc on allocation failure */ -inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size) +inline void* aligned_realloc(void *ptr, std::size_t new_size, std::size_t old_size) { EIGEN_UNUSED_VARIABLE(old_size); @@ -209,12 +209,12 @@ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size) /** \internal Allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned. * On allocation error, the returned pointer is null, and a std::bad_alloc is thrown. */ -template EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(size_t size) +template EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(std::size_t size) { return aligned_malloc(size); } -template<> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(size_t size) +template<> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(std::size_t size) { check_that_malloc_is_allowed(); @@ -235,12 +235,12 @@ template<> EIGEN_DEVICE_FUNC inline void conditional_aligned_free(void *p std::free(ptr); } -template inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size) +template inline void* conditional_aligned_realloc(void* ptr, std::size_t new_size, std::size_t old_size) { return aligned_realloc(ptr, new_size, old_size); } -template<> inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t) +template<> inline void* conditional_aligned_realloc(void* ptr, std::size_t new_size, std::size_t) { return std::realloc(ptr, new_size); } @@ -252,7 +252,7 @@ template<> inline void* conditional_aligned_realloc(void* ptr, size_t new /** \internal Destructs the elements of an array. * The \a size parameters tells on how many objects to call the destructor of T. */ -template EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T *ptr, std::size_t size) { // always destruct an array starting from the end. if(ptr) @@ -262,9 +262,9 @@ template EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T /** \internal Constructs the elements of an array. * The \a size parameter tells on how many objects to call the constructor of T. */ -template EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *ptr, std::size_t size) { - size_t i; + std::size_t i; EIGEN_TRY { for (i = 0; i < size; ++i) ::new (ptr + i) T; @@ -283,9 +283,9 @@ template EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T * *****************************************************************************/ template -EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(size_t size) +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(std::size_t size) { - if(size > size_t(-1) / sizeof(T)) + if(size > std::size_t(-1) / sizeof(T)) throw_std_bad_alloc(); } @@ -293,7 +293,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(size_t size) * On allocation error, the returned pointer is undefined, but a std::bad_alloc is thrown. * The default constructor of T is called. */ -template EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size) +template EIGEN_DEVICE_FUNC inline T* aligned_new(std::size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(aligned_malloc(sizeof(T)*size)); @@ -309,7 +309,7 @@ template EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size) return result; } -template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(size_t size) +template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(std::size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(conditional_aligned_malloc(sizeof(T)*size)); @@ -328,7 +328,7 @@ template EIGEN_DEVICE_FUNC inline T* conditional_aligned /** \internal Deletes objects constructed with aligned_new * The \a size parameters tells on how many objects to call the destructor of T. */ -template EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, std::size_t size) { destruct_elements_of_array(ptr, size); aligned_free(ptr); @@ -337,13 +337,13 @@ template EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, size_t /** \internal Deletes objects constructed with conditional_aligned_new * The \a size parameters tells on how many objects to call the destructor of T. */ -template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete(T *ptr, std::size_t size) { destruct_elements_of_array(ptr, size); conditional_aligned_free(ptr); } -template EIGEN_DEVICE_FUNC inline T* conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size) +template EIGEN_DEVICE_FUNC inline T* conditional_aligned_realloc_new(T* pts, std::size_t new_size, std::size_t old_size) { check_size_for_overflow(new_size); check_size_for_overflow(old_size); @@ -366,7 +366,7 @@ template EIGEN_DEVICE_FUNC inline T* conditional_aligned } -template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new_auto(size_t size) +template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new_auto(std::size_t size) { if(size==0) return 0; // short-cut. Also fixes Bug 884 @@ -387,7 +387,7 @@ template EIGEN_DEVICE_FUNC inline T* conditional_aligned return result; } -template inline T* conditional_aligned_realloc_new_auto(T* pts, size_t new_size, size_t old_size) +template inline T* conditional_aligned_realloc_new_auto(T* pts, std::size_t new_size, std::size_t old_size) { check_size_for_overflow(new_size); check_size_for_overflow(old_size); @@ -409,7 +409,7 @@ template inline T* conditional_aligned_realloc_new_auto( return result; } -template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete_auto(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete_auto(T *ptr, std::size_t size) { if(NumTraits::RequireInitialization) destruct_elements_of_array(ptr, size); @@ -493,7 +493,7 @@ template struct smart_copy_helper { IntPtr size = IntPtr(end)-IntPtr(start); if(size==0) return; eigen_internal_assert(start!=0 && end!=0 && target!=0); - memcpy(target, start, size); + std::memcpy(target, start, size); } }; @@ -561,7 +561,7 @@ template class aligned_stack_memory_handler : noncopyable * In this case, the buffer elements will also be destructed when this handler will be destructed. * Finally, if \a dealloc is true, then the pointer \a ptr is freed. **/ - aligned_stack_memory_handler(T* ptr, size_t size, bool dealloc) + aligned_stack_memory_handler(T* ptr, std::size_t size, bool dealloc) : m_ptr(ptr), m_size(size), m_deallocate(dealloc) { if(NumTraits::RequireInitialization && m_ptr) @@ -576,7 +576,7 @@ template class aligned_stack_memory_handler : noncopyable } protected: T* m_ptr; - size_t m_size; + std::size_t m_size; bool m_deallocate; }; @@ -655,15 +655,15 @@ template void swap(scoped_array &a,scoped_array &b) #if EIGEN_MAX_ALIGN_BYTES!=0 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ - void* operator new(size_t size, const std::nothrow_t&) EIGEN_NO_THROW { \ + void* operator new(std::size_t size, const std::nothrow_t&) EIGEN_NO_THROW { \ EIGEN_TRY { return Eigen::internal::conditional_aligned_malloc(size); } \ EIGEN_CATCH (...) { return 0; } \ } #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \ - void *operator new(size_t size) { \ + void *operator new(std::size_t size) { \ return Eigen::internal::conditional_aligned_malloc(size); \ } \ - void *operator new[](size_t size) { \ + void *operator new[](std::size_t size) { \ return Eigen::internal::conditional_aligned_malloc(size); \ } \ void operator delete(void * ptr) EIGEN_NO_THROW { Eigen::internal::conditional_aligned_free(ptr); } \ @@ -673,8 +673,8 @@ template void swap(scoped_array &a,scoped_array &b) /* in-place new and delete. since (at least afaik) there is no actual */ \ /* memory allocated we can safely let the default implementation handle */ \ /* this particular case. */ \ - static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \ - static void *operator new[](size_t size, void* ptr) { return ::operator new[](size,ptr); } \ + static void *operator new(std::size_t size, void *ptr) { return ::operator new(size,ptr); } \ + static void *operator new[](std::size_t size, void* ptr) { return ::operator new[](size,ptr); } \ void operator delete(void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete(memory,ptr); } \ void operator delete[](void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete[](memory,ptr); } \ /* nothrow-new (returns zero instead of std::bad_alloc) */ \ @@ -696,7 +696,15 @@ template void swap(scoped_array &a,scoped_array &b) /** \class aligned_allocator * \ingroup Core_Module * -* \brief STL compatible allocator to use with with 16 byte aligned types +* \brief STL compatible allocator to use with types requiring a non standrad alignment. +* +* The memory is aligned as for dynamically aligned matrix/array types such as MatrixXd. +* By default, it will thus provide at least 16 bytes alignment and more in following cases: +* - 32 bytes alignment if AVX is enabled. +* - 64 bytes alignment if AVX512 is enabled. +* +* This can be controled using the \c EIGEN_MAX_ALIGN_BYTES macro as documented +* \link TopicPreprocessorDirectivesPerformance there \endlink. * * Example: * \code @@ -713,7 +721,7 @@ template class aligned_allocator : public std::allocator { public: - typedef size_t size_type; + typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; @@ -739,7 +747,15 @@ public: pointer allocate(size_type num, const void* /*hint*/ = 0) { internal::check_size_for_overflow(num); - return static_cast( internal::aligned_malloc(num * sizeof(T)) ); + size_type size = num * sizeof(T); +#if EIGEN_COMP_GNUC_STRICT && EIGEN_GNUC_AT_LEAST(7,0) + // workaround gcc bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87544 + // It triggered eigen/Eigen/src/Core/util/Memory.h:189:12: warning: argument 1 value '18446744073709551612' exceeds maximum object size 9223372036854775807 + if(size>=std::size_t((std::numeric_limits::max)())) + return 0; + else +#endif + return static_cast( internal::aligned_malloc(size) ); } void deallocate(pointer p, size_type /*num*/) diff --git a/eigenlib/Eigen/src/Core/util/Meta.h b/eigenlib/Eigen/src/Core/util/Meta.h index 7f637075..9b61ff03 100755 --- a/eigenlib/Eigen/src/Core/util/Meta.h +++ b/eigenlib/Eigen/src/Core/util/Meta.h @@ -97,6 +97,9 @@ template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; +#if EIGEN_HAS_CXX11 +using std::is_integral; +#else template struct is_integral { enum { value = false }; }; template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; @@ -108,6 +111,33 @@ template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; +#if EIGEN_COMP_MSVC +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral{ enum { value = true }; }; +#endif +#endif + +#if EIGEN_HAS_CXX11 +using std::make_unsigned; +#else +// TODO: Possibly improve this implementation of make_unsigned. +// It is currently used only by +// template struct random_default_impl. +template struct make_unsigned; +template<> struct make_unsigned { typedef unsigned char type; }; +template<> struct make_unsigned { typedef unsigned char type; }; +template<> struct make_unsigned { typedef unsigned char type; }; +template<> struct make_unsigned { typedef unsigned short type; }; +template<> struct make_unsigned { typedef unsigned short type; }; +template<> struct make_unsigned { typedef unsigned int type; }; +template<> struct make_unsigned { typedef unsigned int type; }; +template<> struct make_unsigned { typedef unsigned long type; }; +template<> struct make_unsigned { typedef unsigned long type; }; +#if EIGEN_COMP_MSVC +template<> struct make_unsigned { typedef unsigned __int64 type; }; +template<> struct make_unsigned { typedef unsigned __int64 type; }; +#endif +#endif template struct add_const { typedef const T type; }; template struct add_const { typedef T& type; }; @@ -485,8 +515,54 @@ T div_ceil(const T &a, const T &b) return (a+b-1) / b; } +// The aim of the following functions is to bypass -Wfloat-equal warnings +// when we really want a strict equality comparison on floating points. +template EIGEN_STRONG_INLINE +bool equal_strict(const X& x,const Y& y) { return x == y; } + +template<> EIGEN_STRONG_INLINE +bool equal_strict(const float& x,const float& y) { return std::equal_to()(x,y); } + +template<> EIGEN_STRONG_INLINE +bool equal_strict(const double& x,const double& y) { return std::equal_to()(x,y); } + +template EIGEN_STRONG_INLINE +bool not_equal_strict(const X& x,const Y& y) { return x != y; } + +template<> EIGEN_STRONG_INLINE +bool not_equal_strict(const float& x,const float& y) { return std::not_equal_to()(x,y); } + +template<> EIGEN_STRONG_INLINE +bool not_equal_strict(const double& x,const double& y) { return std::not_equal_to()(x,y); } + } // end namespace numext } // end namespace Eigen +// Define portable (u)int{32,64} types +#if EIGEN_HAS_CXX11 +#include +namespace Eigen { +namespace numext { +typedef std::uint32_t uint32_t; +typedef std::int32_t int32_t; +typedef std::uint64_t uint64_t; +typedef std::int64_t int64_t; +} +} +#else +// Without c++11, all compilers able to compile Eigen also +// provides the C99 stdint.h header file. +#include +namespace Eigen { +namespace numext { +typedef ::uint32_t uint32_t; +typedef ::int32_t int32_t; +typedef ::uint64_t uint64_t; +typedef ::int64_t int64_t; +} +} +#endif + + #endif // EIGEN_META_H diff --git a/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h b/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h index 86b60f52..1ce6fd1b 100644 --- a/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h +++ b/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h @@ -1,4 +1,8 @@ -#ifdef EIGEN_WARNINGS_DISABLED +#ifdef EIGEN_WARNINGS_DISABLED_2 +// "DisableStupidWarnings.h" was included twice recursively: Do not reenable warnings yet! +# undef EIGEN_WARNINGS_DISABLED_2 + +#elif defined(EIGEN_WARNINGS_DISABLED) #undef EIGEN_WARNINGS_DISABLED #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS @@ -8,7 +12,7 @@ #pragma warning pop #elif defined __clang__ #pragma clang diagnostic pop - #elif defined __GNUC__ && __GNUC__>=6 + #elif defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) #pragma GCC diagnostic pop #endif diff --git a/eigenlib/Eigen/src/Core/util/StaticAssert.h b/eigenlib/Eigen/src/Core/util/StaticAssert.h index 983361a4..500e4779 100644 --- a/eigenlib/Eigen/src/Core/util/StaticAssert.h +++ b/eigenlib/Eigen/src/Core/util/StaticAssert.h @@ -24,6 +24,7 @@ * */ +#ifndef EIGEN_STATIC_ASSERT #ifndef EIGEN_NO_STATIC_ASSERT #if EIGEN_MAX_CPP_VER>=11 && (__has_feature(cxx_static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L) || (EIGEN_COMP_MSVC >= 1600)) @@ -44,64 +45,65 @@ struct static_assertion { enum { - YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX, - YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES, - YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES, - THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE, - THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE, - THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE, - OUT_OF_RANGE_ACCESS, - YOU_MADE_A_PROGRAMMING_MISTAKE, - EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT, - EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE, - YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR, - YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR, - UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC, - THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES, - FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED, - NUMERIC_TYPE_MUST_BE_REAL, - COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED, - WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED, - THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE, - INVALID_MATRIX_PRODUCT, - INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS, - INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION, - YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY, - THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES, - THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES, - INVALID_MATRIX_TEMPLATE_PARAMETERS, - INVALID_MATRIXBASE_TEMPLATE_PARAMETERS, - BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER, - THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX, - THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE, - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES, - YOU_ALREADY_SPECIFIED_THIS_STRIDE, - INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION, - THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD, - PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1, - THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS, - YOU_CANNOT_MIX_ARRAYS_AND_MATRICES, - YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION, - THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY, - YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT, - THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS, - THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS, - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL, - THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES, - YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED, - YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED, - THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE, - THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH, - OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG, - IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY, - STORAGE_LAYOUT_DOES_NOT_MATCH, - EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE, - THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS, - MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY, - THIS_TYPE_IS_NOT_SUPPORTED, - STORAGE_KIND_MUST_MATCH, - STORAGE_INDEX_MUST_MATCH, - CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY + YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX=1, + YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES=1, + YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES=1, + THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE=1, + THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE=1, + THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE=1, + OUT_OF_RANGE_ACCESS=1, + YOU_MADE_A_PROGRAMMING_MISTAKE=1, + EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT=1, + EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE=1, + YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR=1, + YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR=1, + UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC=1, + THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES=1, + FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED=1, + NUMERIC_TYPE_MUST_BE_REAL=1, + COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED=1, + WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED=1, + THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE=1, + INVALID_MATRIX_PRODUCT=1, + INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS=1, + INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION=1, + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY=1, + THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES=1, + THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES=1, + INVALID_MATRIX_TEMPLATE_PARAMETERS=1, + INVALID_MATRIXBASE_TEMPLATE_PARAMETERS=1, + BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER=1, + THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX=1, + THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE=1, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES=1, + YOU_ALREADY_SPECIFIED_THIS_STRIDE=1, + INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION=1, + THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD=1, + PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1=1, + THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS=1, + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES=1, + YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION=1, + THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY=1, + YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT=1, + THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS=1, + THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS=1, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL=1, + THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES=1, + YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED=1, + YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED=1, + THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE=1, + THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH=1, + OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG=1, + IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY=1, + STORAGE_LAYOUT_DOES_NOT_MATCH=1, + EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE=1, + THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS=1, + MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY=1, + THIS_TYPE_IS_NOT_SUPPORTED=1, + STORAGE_KIND_MUST_MATCH=1, + STORAGE_INDEX_MUST_MATCH=1, + CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY=1, + SELFADJOINTVIEW_ACCEPTS_UPPER_AND_LOWER_MODE_ONLY=1 }; }; @@ -131,7 +133,7 @@ #define EIGEN_STATIC_ASSERT(CONDITION,MSG) eigen_assert((CONDITION) && #MSG); #endif // EIGEN_NO_STATIC_ASSERT - +#endif // EIGEN_STATIC_ASSERT // static assertion failing if the type \a TYPE is not a vector type #define EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE) \ diff --git a/eigenlib/Eigen/src/Core/util/XprHelper.h b/eigenlib/Eigen/src/Core/util/XprHelper.h index e88510dc..6bb49708 100644 --- a/eigenlib/Eigen/src/Core/util/XprHelper.h +++ b/eigenlib/Eigen/src/Core/util/XprHelper.h @@ -34,6 +34,20 @@ inline IndexDest convert_index(const IndexSrc& idx) { return IndexDest(idx); } +// true if T can be considered as an integral index (i.e., and integral type or enum) +template struct is_valid_index_type +{ + enum { value = +#if EIGEN_HAS_TYPE_TRAITS + internal::is_integral::value || std::is_enum::value +#elif EIGEN_COMP_MSVC + internal::is_integral::value || __is_enum(T) +#else + // without C++11, we use is_convertible to Index instead of is_integral in order to treat enums as Index. + internal::is_convertible::value && !internal::is_same::value && !is_same::value +#endif + }; +}; // promote_scalar_arg is an helper used in operation between an expression and a scalar, like: // expression * scalar @@ -90,6 +104,9 @@ class no_assignment_operator { private: no_assignment_operator& operator=(const no_assignment_operator&); + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(no_assignment_operator) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(no_assignment_operator) }; /** \internal return the index type with the largest number of bits */ @@ -638,7 +655,7 @@ struct plain_constant_type template struct is_lvalue { - enum { value = !bool(is_const::value) && + enum { value = (!bool(is_const::value)) && bool(traits::Flags & LvalueBit) }; }; diff --git a/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h index ec3b1633..dc5fae06 100644 --- a/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h @@ -250,7 +250,7 @@ template class ComplexEigenSolver EigenvectorType m_matX; private: - void doComputeEigenvectors(const RealScalar& matrixnorm); + void doComputeEigenvectors(RealScalar matrixnorm); void sortEigenvalues(bool computeEigenvectors); }; @@ -284,10 +284,12 @@ ComplexEigenSolver::compute(const EigenBase& matrix, bool template -void ComplexEigenSolver::doComputeEigenvectors(const RealScalar& matrixnorm) +void ComplexEigenSolver::doComputeEigenvectors(RealScalar matrixnorm) { const Index n = m_eivalues.size(); + matrixnorm = numext::maxi(matrixnorm,(std::numeric_limits::min)()); + // Compute X such that T = X D X^(-1), where D is the diagonal of T. // The matrix X is unit triangular. m_matX = EigenvectorType::Zero(n, n); diff --git a/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h b/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h index 7f38919f..4354e401 100644 --- a/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h +++ b/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h @@ -300,10 +300,13 @@ typename ComplexSchur::ComplexScalar ComplexSchur::compu ComplexScalar trace = t.coeff(0,0) + t.coeff(1,1); ComplexScalar eival1 = (trace + disc) / RealScalar(2); ComplexScalar eival2 = (trace - disc) / RealScalar(2); - - if(numext::norm1(eival1) > numext::norm1(eival2)) + RealScalar eival1_norm = numext::norm1(eival1); + RealScalar eival2_norm = numext::norm1(eival2); + // A division by zero can only occur if eival1==eival2==0. + // In this case, det==0, and all we have to do is checking that eival2_norm!=0 + if(eival1_norm > eival2_norm) eival2 = det / eival1; - else + else if(eival2_norm!=RealScalar(0)) eival1 = det / eival2; // choose the eigenvalue closest to the bottom entry of the diagonal diff --git a/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h index 36a91dff..87d789b3 100644 --- a/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h @@ -311,7 +311,6 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp // Aliases: Map v(reinterpret_cast(m_tmp.data()), size); ComplexVectorType &cv = m_tmp; - const MatrixType &mZ = m_realQZ.matrixZ(); const MatrixType &mS = m_realQZ.matrixS(); const MatrixType &mT = m_realQZ.matrixT(); @@ -351,7 +350,7 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp } } } - m_eivec.col(i).real().noalias() = mZ.transpose() * v; + m_eivec.col(i).real().noalias() = m_realQZ.matrixZ().transpose() * v; m_eivec.col(i).real().normalize(); m_eivec.col(i).imag().setConstant(0); } @@ -400,7 +399,7 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp / (alpha*mT.coeffRef(j,j) - static_cast(beta*mS.coeffRef(j,j))); } } - m_eivec.col(i+1).noalias() = (mZ.transpose() * cv); + m_eivec.col(i+1).noalias() = (m_realQZ.matrixZ().transpose() * cv); m_eivec.col(i+1).normalize(); m_eivec.col(i) = m_eivec.col(i+1).conjugate(); } diff --git a/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h b/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h index 4fec8af0..e4e42607 100644 --- a/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +++ b/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h @@ -66,7 +66,6 @@ template inline typename MatrixBase::EigenvaluesReturnType MatrixBase::eigenvalues() const { - typedef typename internal::traits::Scalar Scalar; return internal::eigenvalues_selector::IsComplex>::run(derived()); } @@ -88,7 +87,6 @@ template inline typename SelfAdjointView::EigenvaluesReturnType SelfAdjointView::eigenvalues() const { - typedef typename SelfAdjointView::PlainObject PlainObject; PlainObject thisAsMatrix(*this); return SelfAdjointEigenSolver(thisAsMatrix, false).eigenvalues(); } diff --git a/eigenlib/Eigen/src/Eigenvalues/RealSchur.h b/eigenlib/Eigen/src/Eigenvalues/RealSchur.h index d6a339f0..9191519a 100644 --- a/eigenlib/Eigen/src/Eigenvalues/RealSchur.h +++ b/eigenlib/Eigen/src/Eigenvalues/RealSchur.h @@ -236,7 +236,7 @@ template class RealSchur typedef Matrix Vector3s; Scalar computeNormOfT(); - Index findSmallSubdiagEntry(Index iu); + Index findSmallSubdiagEntry(Index iu, const Scalar& considerAsZero); void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift); void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo); void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector); @@ -248,12 +248,24 @@ template template RealSchur& RealSchur::compute(const EigenBase& matrix, bool computeU) { + const Scalar considerAsZero = (std::numeric_limits::min)(); + eigen_assert(matrix.cols() == matrix.rows()); Index maxIters = m_maxIters; if (maxIters == -1) maxIters = m_maxIterationsPerRow * matrix.rows(); Scalar scale = matrix.derived().cwiseAbs().maxCoeff(); + if(scale& RealSchur::computeFromHessenberg(const HessMa Index totalIter = 0; // iteration count for whole matrix Scalar exshift(0); // sum of exceptional shifts Scalar norm = computeNormOfT(); + // sub-diagonal entries smaller than considerAsZero will be treated as zero. + // We use eps^2 to enable more precision in small eigenvalues. + Scalar considerAsZero = numext::maxi( norm * numext::abs2(NumTraits::epsilon()), + (std::numeric_limits::min)() ); - if(norm!=0) + if(norm!=Scalar(0)) { while (iu >= 0) { - Index il = findSmallSubdiagEntry(iu); + Index il = findSmallSubdiagEntry(iu,considerAsZero); // Check for convergence if (il == iu) // One root found @@ -315,7 +331,7 @@ RealSchur& RealSchur::computeFromHessenberg(const HessMa else // No convergence yet { // The firstHouseholderVector vector has to be initialized to something to get rid of a silly GCC warning (-O1 -Wall -DNDEBUG ) - Vector3s firstHouseholderVector(0,0,0), shiftInfo; + Vector3s firstHouseholderVector = Vector3s::Zero(), shiftInfo; computeShift(iu, iter, exshift, shiftInfo); iter = iter + 1; totalIter = totalIter + 1; @@ -352,14 +368,17 @@ inline typename MatrixType::Scalar RealSchur::computeNormOfT() /** \internal Look for single small sub-diagonal element and returns its index */ template -inline Index RealSchur::findSmallSubdiagEntry(Index iu) +inline Index RealSchur::findSmallSubdiagEntry(Index iu, const Scalar& considerAsZero) { using std::abs; Index res = iu; while (res > 0) { Scalar s = abs(m_matT.coeff(res-1,res-1)) + abs(m_matT.coeff(res,res)); - if (abs(m_matT.coeff(res,res-1)) <= NumTraits::epsilon() * s) + + s = numext::maxi(s * NumTraits::epsilon(), considerAsZero); + + if (abs(m_matT.coeff(res,res-1)) <= s) break; res--; } diff --git a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h index a9f56c4f..d37656fa 100644 --- a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h @@ -414,7 +414,8 @@ SelfAdjointEigenSolver& SelfAdjointEigenSolver if(n==1) { - m_eivalues.coeffRef(0,0) = numext::real(matrix.diagonal()[0]); + m_eivec = matrix; + m_eivalues.coeffRef(0,0) = numext::real(m_eivec.coeff(0,0)); if(computeEigenvectors) m_eivec.setOnes(n,n); m_info = Success; @@ -604,7 +605,8 @@ template struct direct_selfadjoint_eigenvalues res, Ref representative) { - using std::abs; + EIGEN_USING_STD_MATH(sqrt) + EIGEN_USING_STD_MATH(abs) Index i0; // Find non-zero column i0 (by construction, there must exist a non zero coefficient on the diagonal): mat.diagonal().cwiseAbs().maxCoeff(&i0); @@ -615,8 +617,8 @@ template struct direct_selfadjoint_eigenvaluesn1) res = c0/std::sqrt(n0); - else res = c1/std::sqrt(n1); + if(n0>n1) res = c0/sqrt(n0); + else res = c1/sqrt(n1); return true; } diff --git a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h index 3891cf88..b0c947dc 100644 --- a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +++ b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h @@ -37,7 +37,7 @@ namespace Eigen { /** \internal Specialization for the data types supported by LAPACKe */ -#define EIGEN_LAPACKE_EIG_SELFADJ(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, EIGCOLROW, LAPACKE_COLROW ) \ +#define EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, EIGCOLROW ) \ template<> template inline \ SelfAdjointEigenSolver >& \ SelfAdjointEigenSolver >::compute(const EigenBase& matrix, int options) \ @@ -47,7 +47,7 @@ SelfAdjointEigenSolver >::compute(c && (options&EigVecMask)!=EigVecMask \ && "invalid option parameter"); \ bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; \ - lapack_int n = internal::convert_index(matrix.cols()), lda, matrix_order, info; \ + lapack_int n = internal::convert_index(matrix.cols()), lda, info; \ m_eivalues.resize(n,1); \ m_subdiag.resize(n-1); \ m_eivec = matrix; \ @@ -63,27 +63,24 @@ SelfAdjointEigenSolver >::compute(c } \ \ lda = internal::convert_index(m_eivec.outerStride()); \ - matrix_order=LAPACKE_COLROW; \ char jobz, uplo='L'/*, range='A'*/; \ jobz = computeEigenvectors ? 'V' : 'N'; \ \ - info = LAPACKE_##LAPACKE_NAME( matrix_order, jobz, uplo, n, (LAPACKE_TYPE*)m_eivec.data(), lda, (LAPACKE_RTYPE*)m_eivalues.data() ); \ + info = LAPACKE_##LAPACKE_NAME( LAPACK_COL_MAJOR, jobz, uplo, n, (LAPACKE_TYPE*)m_eivec.data(), lda, (LAPACKE_RTYPE*)m_eivalues.data() ); \ m_info = (info==0) ? Success : NoConvergence; \ m_isInitialized = true; \ m_eigenvectorsOk = computeEigenvectors; \ return *this; \ } +#define EIGEN_LAPACKE_EIG_SELFADJ(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME ) \ + EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, ColMajor ) \ + EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, RowMajor ) -EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev, ColMajor, LAPACK_COL_MAJOR) - -EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev) +EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev) +EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev) +EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev) } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Geometry/AngleAxis.h b/eigenlib/Eigen/src/Geometry/AngleAxis.h index 0af3c1b0..83ee1be4 100644 --- a/eigenlib/Eigen/src/Geometry/AngleAxis.h +++ b/eigenlib/Eigen/src/Geometry/AngleAxis.h @@ -178,7 +178,7 @@ EIGEN_DEVICE_FUNC AngleAxis& AngleAxis::operator=(const Quaterni if (n != Scalar(0)) { m_angle = Scalar(2)*atan2(n, abs(q.w())); - if(q.w() < 0) + if(q.w() < Scalar(0)) n = -n; m_axis = q.vec() / n; } diff --git a/eigenlib/Eigen/src/Geometry/Quaternion.h b/eigenlib/Eigen/src/Geometry/Quaternion.h index f6ef1bcf..b8182065 100644 --- a/eigenlib/Eigen/src/Geometry/Quaternion.h +++ b/eigenlib/Eigen/src/Geometry/Quaternion.h @@ -43,6 +43,11 @@ class QuaternionBase : public RotationBase typedef typename internal::traits::Scalar Scalar; typedef typename NumTraits::Real RealScalar; typedef typename internal::traits::Coefficients Coefficients; + typedef typename Coefficients::CoeffReturnType CoeffReturnType; + typedef typename internal::conditional::Flags&LvalueBit), + Scalar&, CoeffReturnType>::type NonConstCoeffReturnType; + + enum { Flags = Eigen::internal::traits::Flags }; @@ -58,22 +63,22 @@ class QuaternionBase : public RotationBase /** \returns the \c x coefficient */ - EIGEN_DEVICE_FUNC inline Scalar x() const { return this->derived().coeffs().coeff(0); } + EIGEN_DEVICE_FUNC inline CoeffReturnType x() const { return this->derived().coeffs().coeff(0); } /** \returns the \c y coefficient */ - EIGEN_DEVICE_FUNC inline Scalar y() const { return this->derived().coeffs().coeff(1); } + EIGEN_DEVICE_FUNC inline CoeffReturnType y() const { return this->derived().coeffs().coeff(1); } /** \returns the \c z coefficient */ - EIGEN_DEVICE_FUNC inline Scalar z() const { return this->derived().coeffs().coeff(2); } + EIGEN_DEVICE_FUNC inline CoeffReturnType z() const { return this->derived().coeffs().coeff(2); } /** \returns the \c w coefficient */ - EIGEN_DEVICE_FUNC inline Scalar w() const { return this->derived().coeffs().coeff(3); } + EIGEN_DEVICE_FUNC inline CoeffReturnType w() const { return this->derived().coeffs().coeff(3); } - /** \returns a reference to the \c x coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& x() { return this->derived().coeffs().coeffRef(0); } - /** \returns a reference to the \c y coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& y() { return this->derived().coeffs().coeffRef(1); } - /** \returns a reference to the \c z coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& z() { return this->derived().coeffs().coeffRef(2); } - /** \returns a reference to the \c w coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& w() { return this->derived().coeffs().coeffRef(3); } + /** \returns a reference to the \c x coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType x() { return this->derived().coeffs().x(); } + /** \returns a reference to the \c y coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType y() { return this->derived().coeffs().y(); } + /** \returns a reference to the \c z coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType z() { return this->derived().coeffs().z(); } + /** \returns a reference to the \c w coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType w() { return this->derived().coeffs().w(); } /** \returns a read-only vector expression of the imaginary part (x,y,z) */ EIGEN_DEVICE_FUNC inline const VectorBlock vec() const { return coeffs().template head<3>(); } @@ -164,20 +169,38 @@ class QuaternionBase : public RotationBase /** return the result vector of \a v through the rotation*/ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const; + #ifdef EIGEN_PARSED_BY_DOXYGEN /** \returns \c *this with scalar type casted to \a NewScalarType * * Note that if \a NewScalarType is equal to the current scalar type of \c *this * then this function smartly returns a const reference to \c *this. */ template - EIGEN_DEVICE_FUNC inline typename internal::cast_return_type >::type cast() const + EIGEN_DEVICE_FUNC inline typename internal::cast_return_type >::type cast() const; + + #else + + template + EIGEN_DEVICE_FUNC inline + typename internal::enable_if::value,const Derived&>::type cast() const { - return typename internal::cast_return_type >::type(derived()); + return derived(); } + template + EIGEN_DEVICE_FUNC inline + typename internal::enable_if::value,Quaternion >::type cast() const + { + return Quaternion(coeffs().template cast()); + } + #endif + #ifdef EIGEN_QUATERNIONBASE_PLUGIN # include EIGEN_QUATERNIONBASE_PLUGIN #endif +protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(QuaternionBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(QuaternionBase) }; /*************************************************************************** @@ -423,7 +446,7 @@ typedef Map, Aligned> QuaternionMapAlignedd; // Generic Quaternion * Quaternion product // This product can be specialized for a given architecture via the Arch template argument. namespace internal { -template struct quat_product +template struct quat_product { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion run(const QuaternionBase& a, const QuaternionBase& b){ return Quaternion @@ -446,8 +469,7 @@ QuaternionBase::operator* (const QuaternionBase& other) c EIGEN_STATIC_ASSERT((internal::is_same::value), YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) return internal::quat_product::Scalar, - EIGEN_PLAIN_ENUM_MIN(internal::traits::Alignment, internal::traits::Alignment)>::run(*this, other); + typename internal::traits::Scalar>::run(*this, other); } /** \sa operator*(Quaternion) */ @@ -672,7 +694,7 @@ EIGEN_DEVICE_FUNC inline Quaternion::Scalar> // Generic conjugate of a Quaternion namespace internal { -template struct quat_conj +template struct quat_conj { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion run(const QuaternionBase& q){ return Quaternion(q.w(),-q.x(),-q.y(),-q.z()); @@ -691,8 +713,7 @@ EIGEN_DEVICE_FUNC inline Quaternion::Scalar> QuaternionBase::conjugate() const { return internal::quat_conj::Scalar, - internal::traits::Alignment>::run(*this); + typename internal::traits::Scalar>::run(*this); } diff --git a/eigenlib/Eigen/src/Geometry/Scaling.h b/eigenlib/Eigen/src/Geometry/Scaling.h old mode 100755 new mode 100644 index f58ca03d..33eabd81 --- a/eigenlib/Eigen/src/Geometry/Scaling.h +++ b/eigenlib/Eigen/src/Geometry/Scaling.h @@ -14,7 +14,7 @@ namespace Eigen { /** \geometry_module \ingroup Geometry_Module * - * \class Scaling + * \class UniformScaling * * \brief Represents a generic uniform scaling transformation * diff --git a/eigenlib/Eigen/src/Geometry/Transform.h b/eigenlib/Eigen/src/Geometry/Transform.h index 3f31ee45..c21d9e55 100644 --- a/eigenlib/Eigen/src/Geometry/Transform.h +++ b/eigenlib/Eigen/src/Geometry/Transform.h @@ -252,11 +252,11 @@ protected: public: /** Default constructor without initialization of the meaningful coefficients. - * If Mode==Affine, then the last row is set to [0 ... 0 1] */ + * If Mode==Affine or Mode==Isometry, then the last row is set to [0 ... 0 1] */ EIGEN_DEVICE_FUNC inline Transform() { check_template_params(); - internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix); + internal::transform_make_affine<(int(Mode)==Affine || int(Mode)==Isometry) ? Affine : AffineCompact>::run(m_matrix); } EIGEN_DEVICE_FUNC inline Transform(const Transform& other) diff --git a/eigenlib/Eigen/src/Geometry/Translation.h b/eigenlib/Eigen/src/Geometry/Translation.h index 51d9a82e..0e99ce68 100644 --- a/eigenlib/Eigen/src/Geometry/Translation.h +++ b/eigenlib/Eigen/src/Geometry/Translation.h @@ -138,12 +138,6 @@ public: /** \returns the inverse translation (opposite) */ Translation inverse() const { return Translation(-m_coeffs); } - Translation& operator=(const Translation& other) - { - m_coeffs = other.m_coeffs; - return *this; - } - static const Translation Identity() { return Translation(VectorType::Zero()); } /** \returns \c *this with scalar type casted to \a NewScalarType diff --git a/eigenlib/Eigen/src/Geometry/Umeyama.h b/eigenlib/Eigen/src/Geometry/Umeyama.h index 7e933fca..6b755008 100644 --- a/eigenlib/Eigen/src/Geometry/Umeyama.h +++ b/eigenlib/Eigen/src/Geometry/Umeyama.h @@ -87,7 +87,7 @@ struct umeyama_transform_matrix_type * \f{align*} * T = \begin{bmatrix} c\mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{bmatrix} * \f} -* minimizing the resudiual above. This transformation is always returned as an +* minimizing the residual above. This transformation is always returned as an * Eigen::Matrix. */ template diff --git a/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h b/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h index 1a86ff83..f68cab58 100644 --- a/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h +++ b/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h @@ -16,17 +16,23 @@ namespace Eigen { namespace internal { template -struct quat_product +struct quat_product { + enum { + AAlignment = traits::Alignment, + BAlignment = traits::Alignment, + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { Quaternion res; const __m128 mask = _mm_setr_ps(0.f,0.f,0.f,-0.f); - __m128 a = _a.coeffs().template packet(0); - __m128 b = _b.coeffs().template packet(0); + __m128 a = _a.coeffs().template packet(0); + __m128 b = _b.coeffs().template packet(0); __m128 s1 = _mm_mul_ps(vec4f_swizzle1(a,1,2,0,2),vec4f_swizzle1(b,2,0,1,2)); __m128 s2 = _mm_mul_ps(vec4f_swizzle1(a,3,3,3,1),vec4f_swizzle1(b,0,1,2,1)); - pstore(&res.x(), + pstoret( + &res.x(), _mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,vec4f_swizzle1(b,3,3,3,3)), _mm_mul_ps(vec4f_swizzle1(a,2,0,1,0), vec4f_swizzle1(b,1,2,0,0))), @@ -36,14 +42,17 @@ struct quat_product } }; -template -struct quat_conj +template +struct quat_conj { + enum { + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& q) { Quaternion res; const __m128 mask = _mm_setr_ps(-0.f,-0.f,-0.f,0.f); - pstore(&res.x(), _mm_xor_ps(mask, q.coeffs().template packet(0))); + pstoret(&res.x(), _mm_xor_ps(mask, q.coeffs().template packet::Alignment>(0))); return res; } }; @@ -52,6 +61,9 @@ struct quat_conj template struct cross3_impl { + enum { + ResAlignment = traits::type>::Alignment + }; static inline typename plain_matrix_type::type run(const VectorLhs& lhs, const VectorRhs& rhs) { @@ -60,7 +72,7 @@ struct cross3_impl __m128 mul1=_mm_mul_ps(vec4f_swizzle1(a,1,2,0,3),vec4f_swizzle1(b,2,0,1,3)); __m128 mul2=_mm_mul_ps(vec4f_swizzle1(a,2,0,1,3),vec4f_swizzle1(b,1,2,0,3)); typename plain_matrix_type::type res; - pstore(&res.x(),_mm_sub_ps(mul1,mul2)); + pstoret(&res.x(),_mm_sub_ps(mul1,mul2)); return res; } }; @@ -68,9 +80,14 @@ struct cross3_impl -template -struct quat_product +template +struct quat_product { + enum { + BAlignment = traits::Alignment, + ResAlignment = traits >::Alignment + }; + static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { const Packet2d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0)); @@ -78,8 +95,8 @@ struct quat_product Quaternion res; const double* a = _a.coeffs().data(); - Packet2d b_xy = _b.coeffs().template packet(0); - Packet2d b_zw = _b.coeffs().template packet(2); + Packet2d b_xy = _b.coeffs().template packet(0); + Packet2d b_zw = _b.coeffs().template packet(2); Packet2d a_xx = pset1(a[0]); Packet2d a_yy = pset1(a[1]); Packet2d a_zz = pset1(a[2]); @@ -97,9 +114,9 @@ struct quat_product t2 = psub(pmul(a_zz, b_xy), pmul(a_xx, b_zw)); #ifdef EIGEN_VECTORIZE_SSE3 EIGEN_UNUSED_VARIABLE(mask) - pstore(&res.x(), _mm_addsub_pd(t1, preverse(t2))); + pstoret(&res.x(), _mm_addsub_pd(t1, preverse(t2))); #else - pstore(&res.x(), padd(t1, pxor(mask,preverse(t2)))); + pstoret(&res.x(), padd(t1, pxor(mask,preverse(t2)))); #endif /* @@ -111,25 +128,28 @@ struct quat_product t2 = padd(pmul(a_zz, b_zw), pmul(a_xx, b_xy)); #ifdef EIGEN_VECTORIZE_SSE3 EIGEN_UNUSED_VARIABLE(mask) - pstore(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2))); + pstoret(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2))); #else - pstore(&res.z(), psub(t1, pxor(mask,preverse(t2)))); + pstoret(&res.z(), psub(t1, pxor(mask,preverse(t2)))); #endif return res; } }; -template -struct quat_conj +template +struct quat_conj { + enum { + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& q) { Quaternion res; const __m128d mask0 = _mm_setr_pd(-0.,-0.); const __m128d mask2 = _mm_setr_pd(-0.,0.); - pstore(&res.x(), _mm_xor_pd(mask0, q.coeffs().template packet(0))); - pstore(&res.z(), _mm_xor_pd(mask2, q.coeffs().template packet(2))); + pstoret(&res.x(), _mm_xor_pd(mask0, q.coeffs().template packet::Alignment>(0))); + pstoret(&res.z(), _mm_xor_pd(mask2, q.coeffs().template packet::Alignment>(2))); return res; } }; diff --git a/eigenlib/Eigen/src/Householder/BlockHouseholder.h b/eigenlib/Eigen/src/Householder/BlockHouseholder.h index 39bf8c83..01a7ed18 100644 --- a/eigenlib/Eigen/src/Householder/BlockHouseholder.h +++ b/eigenlib/Eigen/src/Householder/BlockHouseholder.h @@ -87,7 +87,8 @@ void apply_block_householder_on_the_left(MatrixType& mat, const VectorsType& vec const TriangularView V(vectors); // A -= V T V^* A - Matrix tmp = V.adjoint() * mat; // FIXME add .noalias() once the triangular product can work inplace if(forward) tmp = T.template triangularView() * tmp; diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h b/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h index 358444af..f66c846e 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h @@ -152,13 +152,28 @@ class LeastSquareDiagonalPreconditioner : public DiagonalPreconditioner<_Scalar> { // Compute the inverse squared-norm of each column of mat m_invdiag.resize(mat.cols()); - for(Index j=0; j0) - m_invdiag(j) = RealScalar(1)/sum; - else - m_invdiag(j) = RealScalar(1); + m_invdiag.setZero(); + for(Index j=0; jRealScalar(0)) + m_invdiag(j) = RealScalar(1)/numext::real(m_invdiag(j)); + } + else + { + for(Index j=0; jRealScalar(0)) + m_invdiag(j) = RealScalar(1)/sum; + else + m_invdiag(j) = RealScalar(1); + } } Base::m_isInitialized = true; return *this; diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h index 395daa8e..f7ce4713 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h @@ -50,7 +50,8 @@ void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x, tol_error = 0; return; } - RealScalar threshold = tol*tol*rhsNorm2; + const RealScalar considerAsZero = (std::numeric_limits::min)(); + RealScalar threshold = numext::maxi(tol*tol*rhsNorm2,considerAsZero); RealScalar residualNorm2 = residual.squaredNorm(); if (residualNorm2 < threshold) { @@ -58,7 +59,7 @@ void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x, tol_error = sqrt(residualNorm2 / rhsNorm2); return; } - + VectorType p(n); p = precond.solve(residual); // initial search direction diff --git a/eigenlib/Eigen/src/Jacobi/Jacobi.h b/eigenlib/Eigen/src/Jacobi/Jacobi.h index d25af8e9..1998c632 100644 --- a/eigenlib/Eigen/src/Jacobi/Jacobi.h +++ b/eigenlib/Eigen/src/Jacobi/Jacobi.h @@ -65,11 +65,11 @@ template class JacobiRotation bool makeJacobi(const MatrixBase&, Index p, Index q); bool makeJacobi(const RealScalar& x, const Scalar& y, const RealScalar& z); - void makeGivens(const Scalar& p, const Scalar& q, Scalar* z=0); + void makeGivens(const Scalar& p, const Scalar& q, Scalar* r=0); protected: - void makeGivens(const Scalar& p, const Scalar& q, Scalar* z, internal::true_type); - void makeGivens(const Scalar& p, const Scalar& q, Scalar* z, internal::false_type); + void makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::true_type); + void makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::false_type); Scalar m_c, m_s; }; @@ -84,7 +84,6 @@ bool JacobiRotation::makeJacobi(const RealScalar& x, const Scalar& y, co { using std::sqrt; using std::abs; - typedef typename NumTraits::Real RealScalar; RealScalar deno = RealScalar(2)*abs(y); if(deno < (std::numeric_limits::min)()) { @@ -133,7 +132,7 @@ inline bool JacobiRotation::makeJacobi(const MatrixBase& m, Ind * \f$ V = \left ( \begin{array}{c} p \\ q \end{array} \right )\f$ yields: * \f$ G^* V = \left ( \begin{array}{c} r \\ 0 \end{array} \right )\f$. * - * The value of \a z is returned if \a z is not null (the default is null). + * The value of \a r is returned if \a r is not null (the default is null). * Also note that G is built such that the cosine is always real. * * Example: \include Jacobi_makeGivens.cpp @@ -146,9 +145,9 @@ inline bool JacobiRotation::makeJacobi(const MatrixBase& m, Ind * \sa MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight() */ template -void JacobiRotation::makeGivens(const Scalar& p, const Scalar& q, Scalar* z) +void JacobiRotation::makeGivens(const Scalar& p, const Scalar& q, Scalar* r) { - makeGivens(p, q, z, typename internal::conditional::IsComplex, internal::true_type, internal::false_type>::type()); + makeGivens(p, q, r, typename internal::conditional::IsComplex, internal::true_type, internal::false_type>::type()); } @@ -298,12 +297,144 @@ inline void MatrixBase::applyOnTheRight(Index p, Index q, const JacobiR } namespace internal { + +template +struct apply_rotation_in_the_plane_selector +{ + static inline void run(Scalar *x, Index incrx, Scalar *y, Index incry, Index size, OtherScalar c, OtherScalar s) + { + for(Index i=0; i +struct apply_rotation_in_the_plane_selector +{ + static inline void run(Scalar *x, Index incrx, Scalar *y, Index incry, Index size, OtherScalar c, OtherScalar s) + { + enum { + PacketSize = packet_traits::size, + OtherPacketSize = packet_traits::size + }; + typedef typename packet_traits::type Packet; + typedef typename packet_traits::type OtherPacket; + + /*** dynamic-size vectorized paths ***/ + if(SizeAtCompileTime == Dynamic && ((incrx==1 && incry==1) || PacketSize == 1)) + { + // both vectors are sequentially stored in memory => vectorization + enum { Peeling = 2 }; + + Index alignedStart = internal::first_default_aligned(y, size); + Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize; + + const OtherPacket pc = pset1(c); + const OtherPacket ps = pset1(s); + conj_helper::IsComplex,false> pcj; + conj_helper pm; + + for(Index i=0; i(px); + Packet yi = pload(py); + pstore(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore(py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + px += PacketSize; + py += PacketSize; + } + } + else + { + Index peelingEnd = alignedStart + ((size-alignedStart)/(Peeling*PacketSize))*(Peeling*PacketSize); + for(Index i=alignedStart; i(px); + Packet xi1 = ploadu(px+PacketSize); + Packet yi = pload (py); + Packet yi1 = pload (py+PacketSize); + pstoreu(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstoreu(px+PacketSize, padd(pm.pmul(pc,xi1),pcj.pmul(ps,yi1))); + pstore (py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + pstore (py+PacketSize, psub(pcj.pmul(pc,yi1),pm.pmul(ps,xi1))); + px += Peeling*PacketSize; + py += Peeling*PacketSize; + } + if(alignedEnd!=peelingEnd) + { + Packet xi = ploadu(x+peelingEnd); + Packet yi = pload (y+peelingEnd); + pstoreu(x+peelingEnd, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore (y+peelingEnd, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + } + } + + for(Index i=alignedEnd; i0) // FIXME should be compared to the required alignment + { + const OtherPacket pc = pset1(c); + const OtherPacket ps = pset1(s); + conj_helper::IsComplex,false> pcj; + conj_helper pm; + Scalar* EIGEN_RESTRICT px = x; + Scalar* EIGEN_RESTRICT py = y; + for(Index i=0; i(px); + Packet yi = pload(py); + pstore(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore(py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + px += PacketSize; + py += PacketSize; + } + } + + /*** non-vectorized path ***/ + else + { + apply_rotation_in_the_plane_selector::run(x,incrx,y,incry,size,c,s); + } + } +}; + template void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(DenseBase& xpr_x, DenseBase& xpr_y, const JacobiRotation& j) { typedef typename VectorX::Scalar Scalar; - enum { PacketSize = packet_traits::size }; - typedef typename packet_traits::type Packet; + const bool Vectorizable = (VectorX::Flags & VectorY::Flags & PacketAccessBit) + && (int(packet_traits::size) == int(packet_traits::size)); + eigen_assert(xpr_x.size() == xpr_y.size()); Index size = xpr_x.size(); Index incrx = xpr_x.derived().innerStride(); @@ -317,113 +448,11 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(DenseBase& xpr_x if (c==OtherScalar(1) && s==OtherScalar(0)) return; - /*** dynamic-size vectorized paths ***/ - - if(VectorX::SizeAtCompileTime == Dynamic && - (VectorX::Flags & VectorY::Flags & PacketAccessBit) && - ((incrx==1 && incry==1) || PacketSize == 1)) - { - // both vectors are sequentially stored in memory => vectorization - enum { Peeling = 2 }; - - Index alignedStart = internal::first_default_aligned(y, size); - Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize; - - const Packet pc = pset1(c); - const Packet ps = pset1(s); - conj_helper::IsComplex,false> pcj; - - for(Index i=0; i(px); - Packet yi = pload(py); - pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - px += PacketSize; - py += PacketSize; - } - } - else - { - Index peelingEnd = alignedStart + ((size-alignedStart)/(Peeling*PacketSize))*(Peeling*PacketSize); - for(Index i=alignedStart; i(px); - Packet xi1 = ploadu(px+PacketSize); - Packet yi = pload (py); - Packet yi1 = pload (py+PacketSize); - pstoreu(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstoreu(px+PacketSize, padd(pmul(pc,xi1),pcj.pmul(ps,yi1))); - pstore (py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - pstore (py+PacketSize, psub(pcj.pmul(pc,yi1),pmul(ps,xi1))); - px += Peeling*PacketSize; - py += Peeling*PacketSize; - } - if(alignedEnd!=peelingEnd) - { - Packet xi = ploadu(x+peelingEnd); - Packet yi = pload (y+peelingEnd); - pstoreu(x+peelingEnd, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore (y+peelingEnd, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - } - } - - for(Index i=alignedEnd; i::Alignment, evaluator::Alignment)>0)) // FIXME should be compared to the required alignment - { - const Packet pc = pset1(c); - const Packet ps = pset1(s); - conj_helper::IsComplex,false> pcj; - Scalar* EIGEN_RESTRICT px = x; - Scalar* EIGEN_RESTRICT py = y; - for(Index i=0; i(px); - Packet yi = pload(py); - pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - px += PacketSize; - py += PacketSize; - } - } - - /*** non-vectorized path ***/ - else - { - for(Index i=0; i::Alignment, evaluator::Alignment), + Vectorizable>::run(x,incrx,y,incry,size,c,s); } } // end namespace internal diff --git a/eigenlib/Eigen/src/LU/InverseImpl.h b/eigenlib/Eigen/src/LU/InverseImpl.h index 018f99b5..f49f2336 100644 --- a/eigenlib/Eigen/src/LU/InverseImpl.h +++ b/eigenlib/Eigen/src/LU/InverseImpl.h @@ -404,7 +404,7 @@ inline void MatrixBase::computeInverseWithCheck( const RealScalar& absDeterminantThreshold ) const { - RealScalar determinant; + Scalar determinant; // i'd love to put some static assertions there, but SFINAE means that they have no effect... eigen_assert(rows() == cols()); computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold); diff --git a/eigenlib/Eigen/src/LU/PartialPivLU.h b/eigenlib/Eigen/src/LU/PartialPivLU.h index d4396188..6b10f39f 100644 --- a/eigenlib/Eigen/src/LU/PartialPivLU.h +++ b/eigenlib/Eigen/src/LU/PartialPivLU.h @@ -519,7 +519,10 @@ void PartialPivLU::compute() // the row permutation is stored as int indices, so just to be sure: eigen_assert(m_lu.rows()::highest()); - m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff(); + if(m_lu.cols()>0) + m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff(); + else + m_l1_norm = RealScalar(0); eigen_assert(m_lu.rows() == m_lu.cols() && "PartialPivLU is only for square (and moreover invertible) matrices"); const Index size = m_lu.rows(); diff --git a/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h b/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h index ebb64a62..4dce2ef2 100644 --- a/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h +++ b/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h @@ -44,7 +44,7 @@ struct compute_inverse_size4 static void run(const MatrixType& mat, ResultType& result) { ActualMatrixType matrix(mat); - EIGEN_ALIGN16 const unsigned int _Sign_PNNP[4] = { 0x00000000, 0x80000000, 0x80000000, 0x00000000 }; + const Packet4f p4f_sign_PNNP = _mm_castsi128_ps(_mm_set_epi32(0x00000000, 0x80000000, 0x80000000, 0x00000000)); // Load the full matrix into registers __m128 _L1 = matrix.template packet( 0); @@ -139,7 +139,7 @@ struct compute_inverse_size4 iC = _mm_sub_ps(iC, _mm_mul_ps(_mm_shuffle_ps(A,A,0xB1), _mm_shuffle_ps(DC,DC,0x66))); rd = _mm_shuffle_ps(rd,rd,0); - rd = _mm_xor_ps(rd, _mm_load_ps((float*)_Sign_PNNP)); + rd = _mm_xor_ps(rd, p4f_sign_PNNP); // iB = C*|B| - D*B#*A iB = _mm_sub_ps(_mm_mul_ps(C,_mm_shuffle_ps(dB,dB,0)), iB); diff --git a/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h b/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h index 933cd564..da85b4d6 100644 --- a/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h +++ b/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h @@ -1004,7 +1004,7 @@ static IndexType find_ordering /* return the number of garbage collections */ COLAMD_ASSERT (head [min_score] >= COLAMD_EMPTY) ; /* get pivot column from head of minimum degree list */ - while (head [min_score] == COLAMD_EMPTY && min_score < n_col) + while (min_score < n_col && head [min_score] == COLAMD_EMPTY) { min_score++ ; } diff --git a/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h b/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h index d2ebfd7b..160d8a52 100644 --- a/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h +++ b/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h @@ -64,28 +64,28 @@ namespace internal typedef typename _MatrixType::StorageIndex StorageIndex; }; - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} s_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} d_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast(vals), perm, invp, reinterpret_cast(x), nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} diff --git a/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h b/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h index 091c3970..98d0e3f2 100644 --- a/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h +++ b/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h @@ -192,7 +192,8 @@ class PardisoImpl : public SparseSolverBase void pardisoInit(int type) { m_type = type; - bool symmetric = std::abs(m_type) < 10; + EIGEN_USING_STD_MATH(abs); + bool symmetric = abs(m_type) < 10; m_iparm[0] = 1; // No solver default m_iparm[1] = 2; // use Metis for the ordering m_iparm[2] = 0; // Reserved. Set to zero. (??Numbers of processors, value of OMP_NUM_THREADS??) diff --git a/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h b/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h index 0e47c833..a7b47d55 100644 --- a/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h +++ b/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h @@ -506,8 +506,8 @@ void ColPivHouseholderQR::computeInPlace() m_colNormsUpdated.coeffRef(k) = m_colNormsDirect.coeffRef(k); } - RealScalar threshold_helper = numext::abs2(m_colNormsUpdated.maxCoeff() * NumTraits::epsilon()) / RealScalar(rows); - RealScalar norm_downdate_threshold = numext::sqrt(NumTraits::epsilon()); + RealScalar threshold_helper = numext::abs2(m_colNormsUpdated.maxCoeff() * NumTraits::epsilon()) / RealScalar(rows); + RealScalar norm_downdate_threshold = numext::sqrt(NumTraits::epsilon()); m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case) m_maxpivot = RealScalar(0); @@ -553,12 +553,12 @@ void ColPivHouseholderQR::computeInPlace() // http://www.netlib.org/lapack/lawnspdf/lawn176.pdf // and used in LAPACK routines xGEQPF and xGEQP3. // See lines 278-297 in http://www.netlib.org/lapack/explore-html/dc/df4/sgeqpf_8f_source.html - if (m_colNormsUpdated.coeffRef(j) != 0) { + if (m_colNormsUpdated.coeffRef(j) != RealScalar(0)) { RealScalar temp = abs(m_qr.coeffRef(k, j)) / m_colNormsUpdated.coeffRef(j); temp = (RealScalar(1) + temp) * (RealScalar(1) - temp); - temp = temp < 0 ? 0 : temp; - RealScalar temp2 = temp * numext::abs2(m_colNormsUpdated.coeffRef(j) / - m_colNormsDirect.coeffRef(j)); + temp = temp < RealScalar(0) ? RealScalar(0) : temp; + RealScalar temp2 = temp * numext::abs2(m_colNormsUpdated.coeffRef(j) / + m_colNormsDirect.coeffRef(j)); if (temp2 <= norm_downdate_threshold) { // The updated norm has become too inaccurate so re-compute the column // norm directly. diff --git a/eigenlib/Eigen/src/SVD/BDCSVD.h b/eigenlib/Eigen/src/SVD/BDCSVD.h index 25fca6f4..a5b73f8f 100644 --- a/eigenlib/Eigen/src/SVD/BDCSVD.h +++ b/eigenlib/Eigen/src/SVD/BDCSVD.h @@ -11,7 +11,7 @@ // Copyright (C) 2013 Jean Ceccato // Copyright (C) 2013 Pierre Zoppitelli // Copyright (C) 2013 Jitse Niesen -// Copyright (C) 2014-2016 Gael Guennebaud +// Copyright (C) 2014-2017 Gael Guennebaud // // Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed @@ -77,6 +77,7 @@ public: typedef _MatrixType MatrixType; typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits::Real RealScalar; + typedef typename NumTraits::Literal Literal; enum { RowsAtCompileTime = MatrixType::RowsAtCompileTime, ColsAtCompileTime = MatrixType::ColsAtCompileTime, @@ -259,7 +260,7 @@ BDCSVD& BDCSVD::compute(const MatrixType& matrix, unsign //**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows RealScalar scale = matrix.cwiseAbs().maxCoeff(); - if(scale==RealScalar(0)) scale = RealScalar(1); + if(scale==Literal(0)) scale = Literal(1); MatrixX copy; if (m_isTranspose) copy = matrix.adjoint()/scale; else copy = matrix/scale; @@ -351,13 +352,13 @@ void BDCSVD::structured_update(Block A, co Index k1=0, k2=0; for(Index j=0; j::divide (Index firstCol, Index lastCol, Index firstRowW, l = m_naiveU.row(1).segment(firstCol, k); f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1); } - if (m_compV) m_naiveV(firstRowW+k, firstColW) = 1; + if (m_compV) m_naiveV(firstRowW+k, firstColW) = Literal(1); if (r0::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n); m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal(); ArrayRef diag = m_workspace.head(n); - diag(0) = 0; + diag(0) = Literal(0); // Allocate space for singular values and vectors singVals.resize(n); @@ -590,7 +591,7 @@ void BDCSVD::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec // but others are interleaved and we must ignore them at this stage. // To this end, let's compute a permutation skipping them: Index actual_n = n; - while(actual_n>1 && diag(actual_n-1)==0) --actual_n; + while(actual_n>1 && diag(actual_n-1)==Literal(0)) --actual_n; Index m = 0; // size of the deflated problem for(Index k=0;kconsiderZero) @@ -691,11 +692,13 @@ template typename BDCSVD::RealScalar BDCSVD::secularEq(RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift) { Index m = perm.size(); - RealScalar res = 1; + RealScalar res = Literal(1); for(Index i=0; i::computeSingVals(const ArrayRef& col0, const ArrayRef& d { using std::abs; using std::swap; + using std::sqrt; Index n = col0.size(); Index actual_n = n; - while(actual_n>1 && col0(actual_n-1)==0) --actual_n; + // Note that here actual_n is computed based on col0(i)==0 instead of diag(i)==0 as above + // because 1) we have diag(i)==0 => col0(i)==0 and 2) if col0(i)==0, then diag(i) is already a singular value. + while(actual_n>1 && col0(actual_n-1)==Literal(0)) --actual_n; for (Index k = 0; k < n; ++k) { - if (col0(k) == 0 || actual_n==1) + if (col0(k) == Literal(0) || actual_n==1) { // if col0(k) == 0, then entry is deflated, so singular value is on diagonal // if actual_n==1, then the deflated problem is already diagonalized singVals(k) = k==0 ? col0(0) : diag(k); - mus(k) = 0; + mus(k) = Literal(0); shifts(k) = k==0 ? col0(0) : diag(k); continue; } @@ -731,15 +737,17 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d right = (diag(actual_n-1) + col0.matrix().norm()); else { - // Skip deflated singular values + // Skip deflated singular values, + // recall that at this stage we assume that z[j]!=0 and all entries for which z[j]==0 have been put aside. + // This should be equivalent to using perm[] Index l = k+1; - while(col0(l)==0) { ++l; eigen_internal_assert(l::computeSingVals(const ArrayRef& col0, const ArrayRef& d << " " << secularEq(0.8*(left+right), col0, diag, perm, diag, 0) << " " << secularEq(0.9*(left+right), col0, diag, perm, diag, 0) << "\n"; #endif - RealScalar shift = (k == actual_n-1 || fMid > 0) ? left : right; + RealScalar shift = (k == actual_n-1 || fMid > Literal(0)) ? left : right; // measure everything relative to shift Map diagShifted(m_workspace.data()+4*n, n); diagShifted = diag - shift; + + if(k!=actual_n-1) + { + // check that after the shift, f(mid) is still negative: + RealScalar midShifted = (right - left) / RealScalar(2); + if(shift==right) + midShifted = -midShifted; + RealScalar fMidShifted = secularEq(midShifted, col0, diag, perm, diagShifted, shift); + if(fMidShifted>0) + { + // fMid was erroneous, fix it: + shift = fMidShifted > Literal(0) ? left : right; + diagShifted = diag - shift; + } + } // initial guess RealScalar muPrev, muCur; @@ -785,13 +808,13 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d // rational interpolation: fit a function of the form a / mu + b through the two previous // iterates and use its zero to compute the next iterate - bool useBisection = fPrev*fCur>0; - while (fCur!=0 && abs(muCur - muPrev) > 8 * NumTraits::epsilon() * numext::maxi(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits::epsilon() && !useBisection) + bool useBisection = fPrev*fCur>Literal(0); + while (fCur!=Literal(0) && abs(muCur - muPrev) > Literal(8) * NumTraits::epsilon() * numext::maxi(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits::epsilon() && !useBisection) { ++m_numIters; // Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples. - RealScalar a = (fCur - fPrev) / (1/muCur - 1/muPrev); + RealScalar a = (fCur - fPrev) / (Literal(1)/muCur - Literal(1)/muPrev); RealScalar b = fCur - a / muCur; // And find mu such that f(mu)==0: RealScalar muZero = -a/b; @@ -803,8 +826,8 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d fCur = fZero; - if (shift == left && (muCur < 0 || muCur > right - left)) useBisection = true; - if (shift == right && (muCur < -(right - left) || muCur > 0)) useBisection = true; + if (shift == left && (muCur < Literal(0) || muCur > right - left)) useBisection = true; + if (shift == right && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true; if (abs(fCur)>abs(fPrev)) useBisection = true; } @@ -817,23 +840,33 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d RealScalar leftShifted, rightShifted; if (shift == left) { - leftShifted = (std::numeric_limits::min)(); + // to avoid overflow, we must have mu > max(real_min, |z(k)|/sqrt(real_max)), + // the factor 2 is to be more conservative + leftShifted = numext::maxi( (std::numeric_limits::min)(), Literal(2) * abs(col0(k)) / sqrt((std::numeric_limits::max)()) ); + + // check that we did it right: + eigen_internal_assert( (numext::isfinite)( (col0(k)/leftShifted)*(col0(k)/(diag(k)+shift+leftShifted)) ) ); // I don't understand why the case k==0 would be special there: - // if (k == 0) rightShifted = right - left; else - rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.6)); // theoretically we can take 0.5, but let's be safe + // if (k == 0) rightShifted = right - left; else + rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.51)); // theoretically we can take 0.5, but let's be safe } else { - leftShifted = -(right - left) * RealScalar(0.6); - rightShifted = -(std::numeric_limits::min)(); + leftShifted = -(right - left) * RealScalar(0.51); + if(k+1( (std::numeric_limits::min)(), abs(col0(k+1)) / sqrt((std::numeric_limits::max)()) ); + else + rightShifted = -(std::numeric_limits::min)(); } RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift); + eigen_internal_assert(fLeft::computeSingVals(const ArrayRef& col0, const ArrayRef& d std::cout << k << " : " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; " << left << " - " << right << " -> " << leftShifted << " " << rightShifted << " shift=" << shift << "\n"; } #endif - eigen_internal_assert(fLeft * fRight < 0); - - while (rightShifted - leftShifted > 2 * NumTraits::epsilon() * numext::maxi(abs(leftShifted), abs(rightShifted))) - { - RealScalar midShifted = (leftShifted + rightShifted) / 2; - fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift); - if (fLeft * fMid < 0) - { - rightShifted = midShifted; - } - else - { - leftShifted = midShifted; - fLeft = fMid; - } - } + eigen_internal_assert(fLeft * fRight < Literal(0)); - muCur = (leftShifted + rightShifted) / 2; + if(fLeft Literal(2) * NumTraits::epsilon() * numext::maxi(abs(leftShifted), abs(rightShifted))) + { + RealScalar midShifted = (leftShifted + rightShifted) / Literal(2); + fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift); + eigen_internal_assert((numext::isfinite)(fMid)); + + if (fLeft * fMid < Literal(0)) + { + rightShifted = midShifted; + } + else + { + leftShifted = midShifted; + fLeft = fMid; + } + } + muCur = (leftShifted + rightShifted) / Literal(2); + } + else + { + // We have a problem as shifting on the left or right give either a positive or negative value + // at the middle of [left,right]... + // Instead fo abbording or entering an infinite loop, + // let's just use the middle as the estimated zero-crossing: + muCur = (right - left) * RealScalar(0.5); + if(shift == right) + muCur = -muCur; + } } singVals[k] = shift + muCur; @@ -892,8 +939,8 @@ void BDCSVD::perturbCol0 // The offset permits to skip deflated entries while computing zhat for (Index k = 0; k < n; ++k) { - if (col0(k) == 0) // deflated - zhat(k) = 0; + if (col0(k) == Literal(0)) // deflated + zhat(k) = Literal(0); else { // see equation (3.6) @@ -908,7 +955,7 @@ void BDCSVD::perturbCol0 Index j = i 0.9 ) + if(i!=k && numext::abs(((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) - 1) > 0.9 ) std::cout << " " << ((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) << " == (" << (singVals(j)+dk) << " * " << (mus(j)+(shifts(j)-dk)) << ") / (" << (diag(i)+dk) << " * " << (diag(i)-dk) << ")\n"; #endif @@ -918,7 +965,7 @@ void BDCSVD::perturbCol0 std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(last) + dk) << " * " << mus(last) + shifts(last) << " - " << dk << "\n"; #endif RealScalar tmp = sqrt(prod); - zhat(k) = col0(k) > 0 ? tmp : -tmp; + zhat(k) = col0(k) > Literal(0) ? RealScalar(tmp) : RealScalar(-tmp); } } } @@ -934,7 +981,7 @@ void BDCSVD::computeSingVecs for (Index k = 0; k < n; ++k) { - if (zhat(k) == 0) + if (zhat(k) == Literal(0)) { U.col(k) = VectorType::Unit(n+1, k); if (m_compV) V.col(k) = VectorType::Unit(n, k); @@ -947,7 +994,7 @@ void BDCSVD::computeSingVecs Index i = perm(l); U(i,k) = zhat(i)/(((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k])); } - U(n,k) = 0; + U(n,k) = Literal(0); U.col(k).normalize(); if (m_compV) @@ -958,7 +1005,7 @@ void BDCSVD::computeSingVecs Index i = perm(l); V(i,k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k])); } - V(0,k) = -1; + V(0,k) = Literal(-1); V.col(k).normalize(); } } @@ -979,15 +1026,15 @@ void BDCSVD::deflation43(Index firstCol, Index shift, Index i, Index Index start = firstCol + shift; RealScalar c = m_computed(start, start); RealScalar s = m_computed(start+i, start); - RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s)); - if (r == 0) + RealScalar r = numext::hypot(c,s); + if (r == Literal(0)) { - m_computed(start+i, start+i) = 0; + m_computed(start+i, start+i) = Literal(0); return; } m_computed(start,start) = r; - m_computed(start+i, start) = 0; - m_computed(start+i, start+i) = 0; + m_computed(start+i, start) = Literal(0); + m_computed(start+i, start+i) = Literal(0); JacobiRotation J(c/r,-s/r); if (m_compU) m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J); @@ -1020,7 +1067,7 @@ void BDCSVD::deflation44(Index firstColu , Index firstColm, Index fi << m_computed(firstColm + i+1, firstColm+i+1) << " " << m_computed(firstColm + i+2, firstColm+i+2) << "\n"; #endif - if (r==0) + if (r==Literal(0)) { m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j); return; @@ -1029,7 +1076,7 @@ void BDCSVD::deflation44(Index firstColu , Index firstColm, Index fi s/=r; m_computed(firstColm + i, firstColm) = r; m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i); - m_computed(firstColm + j, firstColm) = 0; + m_computed(firstColm + j, firstColm) = Literal(0); JacobiRotation J(c,-s); if (m_compU) m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J); @@ -1053,7 +1100,7 @@ void BDCSVD::deflation(Index firstCol, Index lastCol, Index k, Index const RealScalar considerZero = (std::numeric_limits::min)(); RealScalar maxDiag = diag.tail((std::max)(Index(1),length-1)).cwiseAbs().maxCoeff(); RealScalar epsilon_strict = numext::maxi(considerZero,NumTraits::epsilon() * maxDiag); - RealScalar epsilon_coarse = 8 * NumTraits::epsilon() * numext::maxi(col0.cwiseAbs().maxCoeff(), maxDiag); + RealScalar epsilon_coarse = Literal(8) * NumTraits::epsilon() * numext::maxi(col0.cwiseAbs().maxCoeff(), maxDiag); #ifdef EIGEN_BDCSVD_SANITY_CHECKS assert(m_naiveU.allFinite()); @@ -1081,7 +1128,7 @@ void BDCSVD::deflation(Index firstCol, Index lastCol, Index k, Index #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict << " (diag(" << i << ")=" << diag(i) << ")\n"; #endif - col0(i) = 0; + col0(i) = Literal(0); } //condition 4.3 diff --git a/eigenlib/Eigen/src/SVD/JacobiSVD.h b/eigenlib/Eigen/src/SVD/JacobiSVD.h index e0cfb628..43488b1e 100644 --- a/eigenlib/Eigen/src/SVD/JacobiSVD.h +++ b/eigenlib/Eigen/src/SVD/JacobiSVD.h @@ -112,9 +112,11 @@ public: ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, - Options = MatrixType::Options + TrOptions = RowsAtCompileTime==1 ? (MatrixType::Options & ~(RowMajor)) + : ColsAtCompileTime==1 ? (MatrixType::Options | RowMajor) + : MatrixType::Options }; - typedef Matrix + typedef Matrix TransposeTypeWithSameStorageOrder; void allocate(const JacobiSVD& svd) @@ -200,10 +202,12 @@ public: ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, - Options = MatrixType::Options + TrOptions = RowsAtCompileTime==1 ? (MatrixType::Options & ~(RowMajor)) + : ColsAtCompileTime==1 ? (MatrixType::Options | RowMajor) + : MatrixType::Options }; - typedef Matrix + typedef Matrix TransposeTypeWithSameStorageOrder; void allocate(const JacobiSVD& svd) diff --git a/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h b/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h index 50272154..ff0516f6 100644 --- a/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h +++ b/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h @@ -61,9 +61,10 @@ JacobiSVD, ColPiv u = (LAPACKE_TYPE*)m_matrixU.data(); \ } else { ldu=1; u=&dummy; }\ MatrixType localV; \ - ldvt = (m_computeFullV) ? internal::convert_index(m_cols) : (m_computeThinV) ? internal::convert_index(m_diagSize) : 1; \ + lapack_int vt_rows = (m_computeFullV) ? internal::convert_index(m_cols) : (m_computeThinV) ? internal::convert_index(m_diagSize) : 1; \ if (computeV()) { \ - localV.resize(ldvt, m_cols); \ + localV.resize(vt_rows, m_cols); \ + ldvt = internal::convert_index(localV.outerStride()); \ vt = (LAPACKE_TYPE*)localV.data(); \ } else { ldvt=1; vt=&dummy; }\ Matrix superb; superb.resize(m_diagSize, 1); \ diff --git a/eigenlib/Eigen/src/SVD/SVDBase.h b/eigenlib/Eigen/src/SVD/SVDBase.h index cc90a3b7..53da2848 100644 --- a/eigenlib/Eigen/src/SVD/SVDBase.h +++ b/eigenlib/Eigen/src/SVD/SVDBase.h @@ -180,8 +180,10 @@ public: RealScalar threshold() const { eigen_assert(m_isInitialized || m_usePrescribedThreshold); + // this temporary is needed to workaround a MSVC issue + Index diagSize = (std::max)(1,m_diagSize); return m_usePrescribedThreshold ? m_prescribedThreshold - : (std::max)(1,m_diagSize)*NumTraits::epsilon(); + : RealScalar(diagSize)*NumTraits::epsilon(); } /** \returns true if \a U (full or thin) is asked for in this SVD decomposition */ diff --git a/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h b/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h index 0b146089..11ac847e 100644 --- a/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h +++ b/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h @@ -159,6 +159,8 @@ void upperbidiagonalization_blocked_helper(MatrixType& A, traits::Flags & RowMajorBit> > Y) { typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename NumTraits::Literal Literal; enum { StorageOrder = traits::Flags & RowMajorBit }; typedef InnerStride ColInnerStride; typedef InnerStride RowInnerStride; @@ -263,7 +265,7 @@ void upperbidiagonalization_blocked_helper(MatrixType& A, SubMatType A10( A.block(bs,0, brows-bs,bs) ); SubMatType A01( A.block(0,bs, bs,bcols-bs) ); Scalar tmp = A01(bs-1,0); - A01(bs-1,0) = 1; + A01(bs-1,0) = Literal(1); A11.noalias() -= A10 * Y.topLeftCorner(bcols,bs).bottomRows(bcols-bs).adjoint(); A11.noalias() -= X.topLeftCorner(brows,bs).bottomRows(brows-bs) * A01; A01(bs-1,0) = tmp; diff --git a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h index 2907f652..369e6804 100644 --- a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h +++ b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h @@ -608,7 +608,7 @@ public: } if(Base::m_diag.size()>0) - dest = Base::m_diag.asDiagonal().inverse() * dest; + dest = Base::m_diag.real().asDiagonal().inverse() * dest; if (Base::m_matrix.nonZeros()>0) // otherwise I==I { diff --git a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h index 31e06995..7b6183d0 100644 --- a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +++ b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h @@ -156,7 +156,7 @@ void SimplicialCholeskyBase::factorize_preordered(const CholMatrixType& /* the nonzero entry L(k,i) */ Scalar l_ki; if(DoLDLT) - l_ki = yi / m_diag[i]; + l_ki = yi / numext::real(m_diag[i]); else yi = l_ki = yi / Lx[Lp[i]]; diff --git a/eigenlib/Eigen/src/SparseCore/AmbiVector.h b/eigenlib/Eigen/src/SparseCore/AmbiVector.h index 1233e164..2cb7747c 100644 --- a/eigenlib/Eigen/src/SparseCore/AmbiVector.h +++ b/eigenlib/Eigen/src/SparseCore/AmbiVector.h @@ -28,7 +28,7 @@ class AmbiVector typedef typename NumTraits::Real RealScalar; explicit AmbiVector(Index size) - : m_buffer(0), m_zero(0), m_size(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1) + : m_buffer(0), m_zero(0), m_size(0), m_end(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1) { resize(size); } @@ -94,7 +94,7 @@ class AmbiVector Index allocSize = m_allocatedElements * sizeof(ListEl); allocSize = (allocSize + sizeof(Scalar) - 1)/sizeof(Scalar); Scalar* newBuffer = new Scalar[allocSize]; - memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl)); + std::memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl)); delete[] m_buffer; m_buffer = newBuffer; } @@ -147,7 +147,8 @@ template void AmbiVector<_Scalar,_StorageIndex>::init(int mode) { m_mode = mode; - if (m_mode==IsSparse) + // This is only necessary in sparse mode, but we set these unconditionally to avoid some maybe-uninitialized warnings + // if (m_mode==IsSparse) { m_llSize = 0; m_llStart = -1; @@ -336,7 +337,7 @@ class AmbiVector<_Scalar,_StorageIndex>::Iterator { do { ++m_cachedIndex; - } while (m_cachedIndex::Iterator ListEl* EIGEN_RESTRICT llElements = reinterpret_cast(m_vector.m_buffer); do { m_currentEl = llElements[m_currentEl].next; - } while (m_currentEl>=0 && abs(llElements[m_currentEl].value)=0 && abs(llElements[m_currentEl].value)<=m_epsilon); if (m_currentEl<0) { m_cachedIndex = -1; @@ -363,9 +364,9 @@ class AmbiVector<_Scalar,_StorageIndex>::Iterator protected: const AmbiVector& m_vector; // the target vector - StorageIndex m_currentEl; // the current element in sparse/linked-list mode + StorageIndex m_currentEl; // the current element in sparse/linked-list mode RealScalar m_epsilon; // epsilon used to prune zero coefficients - StorageIndex m_cachedIndex; // current coordinate + StorageIndex m_cachedIndex; // current coordinate Scalar m_cachedValue; // current value bool m_isDense; // mode of the vector }; diff --git a/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h b/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h index 492eb0a2..9db119b6 100644 --- a/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +++ b/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h @@ -17,7 +17,9 @@ namespace internal { template static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res, bool sortedInsertion = false) { - typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Scalar LhsScalar; + typedef typename remove_all::type::Scalar RhsScalar; + typedef typename remove_all::type::Scalar ResScalar; // make sure to call innerSize/outerSize since we fake the storage order. Index rows = lhs.innerSize(); @@ -25,7 +27,7 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r eigen_assert(lhs.outerSize() == rhs.innerSize()); ei_declare_aligned_stack_constructed_variable(bool, mask, rows, 0); - ei_declare_aligned_stack_constructed_variable(Scalar, values, rows, 0); + ei_declare_aligned_stack_constructed_variable(ResScalar, values, rows, 0); ei_declare_aligned_stack_constructed_variable(Index, indices, rows, 0); std::memset(mask,0,sizeof(bool)*rows); @@ -51,12 +53,12 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r Index nnz = 0; for (typename evaluator::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) { - Scalar y = rhsIt.value(); + RhsScalar y = rhsIt.value(); Index k = rhsIt.index(); for (typename evaluator::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) { Index i = lhsIt.index(); - Scalar x = lhsIt.value(); + LhsScalar x = lhsIt.value(); if(!mask[i]) { mask[i] = true; @@ -166,11 +168,12 @@ struct conservative_sparse_sparse_product_selector RowMajorMatrix; - RowMajorMatrix rhsRow = rhs; - RowMajorMatrix resRow(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(rhsRow, lhs, resRow); - res = resRow; + typedef SparseMatrix RowMajorRhs; + typedef SparseMatrix RowMajorRes; + RowMajorRhs rhsRow = rhs; + RowMajorRes resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhsRow, lhs, resRow); + res = resRow; } }; @@ -179,10 +182,11 @@ struct conservative_sparse_sparse_product_selector RowMajorMatrix; - RowMajorMatrix lhsRow = lhs; - RowMajorMatrix resRow(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(rhs, lhsRow, resRow); + typedef SparseMatrix RowMajorLhs; + typedef SparseMatrix RowMajorRes; + RowMajorLhs lhsRow = lhs; + RowMajorRes resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhs, lhsRow, resRow); res = resRow; } }; @@ -219,10 +223,11 @@ struct conservative_sparse_sparse_product_selector ColMajorMatrix; - ColMajorMatrix lhsCol = lhs; - ColMajorMatrix resCol(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(lhsCol, rhs, resCol); + typedef SparseMatrix ColMajorLhs; + typedef SparseMatrix ColMajorRes; + ColMajorLhs lhsCol = lhs; + ColMajorRes resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhsCol, rhs, resCol); res = resCol; } }; @@ -232,10 +237,11 @@ struct conservative_sparse_sparse_product_selector ColMajorMatrix; - ColMajorMatrix rhsCol = rhs; - ColMajorMatrix resCol(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(lhs, rhsCol, resCol); + typedef SparseMatrix ColMajorRhs; + typedef SparseMatrix ColMajorRes; + ColMajorRhs rhsCol = rhs; + ColMajorRes resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhs, rhsCol, resCol); res = resCol; } }; @@ -263,7 +269,8 @@ namespace internal { template static void sparse_sparse_to_dense_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res) { - typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Scalar LhsScalar; + typedef typename remove_all::type::Scalar RhsScalar; Index cols = rhs.outerSize(); eigen_assert(lhs.outerSize() == rhs.innerSize()); @@ -274,12 +281,12 @@ static void sparse_sparse_to_dense_product_impl(const Lhs& lhs, const Rhs& rhs, { for (typename evaluator::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) { - Scalar y = rhsIt.value(); + RhsScalar y = rhsIt.value(); Index k = rhsIt.index(); for (typename evaluator::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) { Index i = lhsIt.index(); - Scalar x = lhsIt.value(); + LhsScalar x = lhsIt.value(); res.coeffRef(i,j) += x * y; } } @@ -310,9 +317,9 @@ struct sparse_sparse_to_dense_product_selector ColMajorMatrix; - ColMajorMatrix lhsCol(lhs); - internal::sparse_sparse_to_dense_product_impl(lhsCol, rhs, res); + typedef SparseMatrix ColMajorLhs; + ColMajorLhs lhsCol(lhs); + internal::sparse_sparse_to_dense_product_impl(lhsCol, rhs, res); } }; @@ -321,9 +328,9 @@ struct sparse_sparse_to_dense_product_selector ColMajorMatrix; - ColMajorMatrix rhsCol(rhs); - internal::sparse_sparse_to_dense_product_impl(lhs, rhsCol, res); + typedef SparseMatrix ColMajorRhs; + ColMajorRhs rhsCol(rhs); + internal::sparse_sparse_to_dense_product_impl(lhs, rhsCol, res); } }; diff --git a/eigenlib/Eigen/src/SparseCore/SparseAssign.h b/eigenlib/Eigen/src/SparseCore/SparseAssign.h index 83776645..18352a84 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseAssign.h +++ b/eigenlib/Eigen/src/SparseCore/SparseAssign.h @@ -143,10 +143,7 @@ struct Assignment dst.setZero(); internal::evaluator srcEval(src); - Index dstRows = src.rows(); - Index dstCols = src.cols(); - if((dst.rows()!=dstRows) || (dst.cols()!=dstCols)) - dst.resize(dstRows, dstCols); + resize_if_allowed(dst, src, func); internal::evaluator dstEval(dst); const Index outerEvaluationSize = (internal::evaluator::Flags&RowMajorBit) ? src.rows() : src.cols(); diff --git a/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h b/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h index e0850795..5ccb4665 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h +++ b/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h @@ -279,11 +279,11 @@ struct evaluator > Flags = Derived::Flags }; - evaluator() : m_matrix(0) + evaluator() : m_matrix(0), m_zero(0) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); } - explicit evaluator(const Derived &mat) : m_matrix(&mat) + explicit evaluator(const Derived &mat) : m_matrix(&mat), m_zero(0) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); } @@ -296,26 +296,42 @@ struct evaluator > operator const Derived&() const { return *m_matrix; } typedef typename DenseCoeffsBase::CoeffReturnType CoeffReturnType; - Scalar coeff(Index row, Index col) const - { return m_matrix->coeff(row,col); } - + const Scalar& coeff(Index row, Index col) const + { + Index p = find(row,col); + + if(p==Dynamic) + return m_zero; + else + return m_matrix->const_cast_derived().valuePtr()[p]; + } + Scalar& coeffRef(Index row, Index col) + { + Index p = find(row,col); + eigen_assert(p!=Dynamic && "written coefficient does not exist"); + return m_matrix->const_cast_derived().valuePtr()[p]; + } + +protected: + + Index find(Index row, Index col) const { eigen_internal_assert(row>=0 && rowrows() && col>=0 && colcols()); - + const Index outer = Derived::IsRowMajor ? row : col; const Index inner = Derived::IsRowMajor ? col : row; Index start = m_matrix->outerIndexPtr()[outer]; Index end = m_matrix->isCompressed() ? m_matrix->outerIndexPtr()[outer+1] : m_matrix->outerIndexPtr()[outer] + m_matrix->innerNonZeroPtr()[outer]; - eigen_assert(end>start && "you are using a non finalized sparse matrix or written coefficient does not exist"); - const Index p = std::lower_bound(m_matrix->innerIndexPtr()+start, m_matrix->innerIndexPtr()+end,inner) - - m_matrix->innerIndexPtr(); - eigen_assert((pinnerIndexPtr()[p]==inner) && "written coefficient does not exist"); - return m_matrix->const_cast_derived().valuePtr()[p]; + eigen_assert(end>=start && "you are using a non finalized sparse matrix or written coefficient does not exist"); + const Index p = std::lower_bound(m_matrix->innerIndexPtr()+start, m_matrix->innerIndexPtr()+end,inner) - m_matrix->innerIndexPtr(); + + return ((pinnerIndexPtr()[p]==inner)) ? p : Dynamic; } const Derived *m_matrix; + const Scalar m_zero; }; } diff --git a/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h index 526c7121..e315e355 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +++ b/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -359,6 +359,16 @@ struct binary_evaluator, Lhs, Rhs>, Itera explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} }; +// "sparse ./ dense" +template +struct binary_evaluator, Lhs, Rhs>, IteratorBased, IndexBased> + : sparse_conjunction_evaluator, Lhs, Rhs> > +{ + typedef CwiseBinaryOp, Lhs, Rhs> XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; + // "sparse && sparse" template struct binary_evaluator, IteratorBased, IteratorBased> diff --git a/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h index ea797379..df6c28d2 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +++ b/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h @@ -49,6 +49,7 @@ template class unary_evaluator, IteratorBased>::InnerIterator : public unary_evaluator, IteratorBased>::EvalIterator { + protected: typedef typename XprType::Scalar Scalar; typedef typename unary_evaluator, IteratorBased>::EvalIterator Base; public: @@ -99,6 +100,7 @@ template class unary_evaluator, IteratorBased>::InnerIterator : public unary_evaluator, IteratorBased>::EvalIterator { + protected: typedef typename XprType::Scalar Scalar; typedef typename unary_evaluator, IteratorBased>::EvalIterator Base; public: diff --git a/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h b/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h index e4af49e0..941c03be 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h +++ b/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h @@ -80,6 +80,8 @@ public: sparse_diagonal_product_evaluator(const SparseXprType &sparseXpr, const DiagonalCoeffType &diagCoeff) : m_sparseXprImpl(sparseXpr), m_diagCoeffImpl(diagCoeff) {} + + Index nonZerosEstimate() const { return m_sparseXprImpl.nonZerosEstimate(); } protected: evaluator m_sparseXprImpl; @@ -121,6 +123,8 @@ struct sparse_diagonal_product_evaluator m_sparseXprEval; diff --git a/eigenlib/Eigen/src/SparseCore/SparseMatrix.h b/eigenlib/Eigen/src/SparseCore/SparseMatrix.h index 529c7a0a..a5396538 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseMatrix.h +++ b/eigenlib/Eigen/src/SparseCore/SparseMatrix.h @@ -327,7 +327,8 @@ class SparseMatrix m_outerIndex[j] = newOuterIndex[j]; m_innerNonZeros[j] = innerNNZ; } - m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize-1] + m_innerNonZeros[m_outerSize-1] + reserveSizes[m_outerSize-1]; + if(m_outerSize>0) + m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize-1] + m_innerNonZeros[m_outerSize-1] + reserveSizes[m_outerSize-1]; m_data.resize(m_outerIndex[m_outerSize]); } @@ -893,7 +894,7 @@ public: Index p = m_outerIndex[outer] + m_innerNonZeros[outer]++; m_data.index(p) = convert_index(inner); - return (m_data.value(p) = 0); + return (m_data.value(p) = Scalar(0)); } private: @@ -1274,7 +1275,7 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& m_innerNonZeros[outer]++; m_data.index(p) = inner; - return (m_data.value(p) = 0); + return (m_data.value(p) = Scalar(0)); } template @@ -1301,11 +1302,11 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g., // the 2nd inner vector... bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0)) - && (size_t(m_outerIndex[outer+1]) == m_data.size()); + && (std::size_t(m_outerIndex[outer+1]) == m_data.size()); - size_t startId = m_outerIndex[outer]; - // FIXME let's make sure sizeof(long int) == sizeof(size_t) - size_t p = m_outerIndex[outer+1]; + std::size_t startId = m_outerIndex[outer]; + // FIXME let's make sure sizeof(long int) == sizeof(std::size_t) + std::size_t p = m_outerIndex[outer+1]; ++m_outerIndex[outer+1]; double reallocRatio = 1; @@ -1381,7 +1382,7 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& } m_data.index(p) = inner; - return (m_data.value(p) = 0); + return (m_data.value(p) = Scalar(0)); } namespace internal { diff --git a/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h b/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h index 9e39be73..76117a01 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h +++ b/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h @@ -47,6 +47,7 @@ template class SparseSelfAdjointView enum { Mode = _Mode, + TransposeMode = ((Mode & Upper) ? Lower : 0) | ((Mode & Lower) ? Upper : 0), RowsAtCompileTime = internal::traits::RowsAtCompileTime, ColsAtCompileTime = internal::traits::ColsAtCompileTime }; @@ -310,7 +311,7 @@ inline void sparse_selfadjoint_time_dense_product(const SparseLhsType& lhs, cons while (i && i.index() dstT(dst); - internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, alpha); + internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, alpha); } }; @@ -452,7 +453,7 @@ void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix::type::Scalar Scalar; + typedef typename remove_all::type::Scalar RhsScalar; + typedef typename remove_all::type::Scalar ResScalar; typedef typename remove_all::type::StorageIndex StorageIndex; // make sure to call innerSize/outerSize since we fake the storage order. @@ -31,7 +32,7 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r eigen_assert(lhs.outerSize() == rhs.innerSize()); // allocate a temporary buffer - AmbiVector tempVector(rows); + AmbiVector tempVector(rows); // mimics a resizeByInnerOuter: if(ResultType::IsRowMajor) @@ -63,14 +64,14 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r { // FIXME should be written like this: tmp += rhsIt.value() * lhs.col(rhsIt.index()) tempVector.restart(); - Scalar x = rhsIt.value(); + RhsScalar x = rhsIt.value(); for (typename evaluator::InnerIterator lhsIt(lhsEval, rhsIt.index()); lhsIt; ++lhsIt) { tempVector.coeffRef(lhsIt.index()) += lhsIt.value() * x; } } res.startVec(j); - for (typename AmbiVector::Iterator it(tempVector,tolerance); it; ++it) + for (typename AmbiVector::Iterator it(tempVector,tolerance); it; ++it) res.insertBackByOuterInner(j,it.index()) = it.value(); } res.finalize(); @@ -85,7 +86,6 @@ struct sparse_sparse_product_with_pruning_selector; template struct sparse_sparse_product_with_pruning_selector { - typedef typename traits::type>::Scalar Scalar; typedef typename ResultType::RealScalar RealScalar; static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance) @@ -129,8 +129,8 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixLhs; - typedef SparseMatrix ColMajorMatrixRhs; + typedef SparseMatrix ColMajorMatrixLhs; + typedef SparseMatrix ColMajorMatrixRhs; ColMajorMatrixLhs colLhs(lhs); ColMajorMatrixRhs colRhs(rhs); internal::sparse_sparse_product_with_pruning_impl(colLhs, colRhs, res, tolerance); @@ -149,7 +149,7 @@ struct sparse_sparse_product_with_pruning_selector RowMajorMatrixLhs; + typedef SparseMatrix RowMajorMatrixLhs; RowMajorMatrixLhs rowLhs(lhs); sparse_sparse_product_with_pruning_selector(rowLhs,rhs,res,tolerance); } @@ -161,7 +161,7 @@ struct sparse_sparse_product_with_pruning_selector RowMajorMatrixRhs; + typedef SparseMatrix RowMajorMatrixRhs; RowMajorMatrixRhs rowRhs(rhs); sparse_sparse_product_with_pruning_selector(lhs,rowRhs,res,tolerance); } @@ -173,7 +173,7 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixRhs; + typedef SparseMatrix ColMajorMatrixRhs; ColMajorMatrixRhs colRhs(rhs); internal::sparse_sparse_product_with_pruning_impl(lhs, colRhs, res, tolerance); } @@ -185,7 +185,7 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixLhs; + typedef SparseMatrix ColMajorMatrixLhs; ColMajorMatrixLhs colLhs(lhs); internal::sparse_sparse_product_with_pruning_impl(colLhs, rhs, res, tolerance); } diff --git a/eigenlib/Eigen/src/SparseCore/SparseView.h b/eigenlib/Eigen/src/SparseCore/SparseView.h index 7c4aea74..92b3d1f7 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseView.h +++ b/eigenlib/Eigen/src/SparseCore/SparseView.h @@ -90,6 +90,7 @@ struct unary_evaluator, IteratorBased> class InnerIterator : public EvalIterator { + protected: typedef typename XprType::Scalar Scalar; public: diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU.h b/eigenlib/Eigen/src/SparseLU/SparseLU.h index f883ab38..87f0efe3 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU.h @@ -43,8 +43,8 @@ template struct SparseLUMatrixURetu * Simple example with key steps * \code * VectorXd x(n), b(n); - * SparseMatrix A; - * SparseLU, COLAMDOrdering > solver; + * SparseMatrix A; + * SparseLU, COLAMDOrdering > solver; * // fill A and b; * // Compute the ordering permutation vector from the structural pattern of A * solver.analyzePattern(A); @@ -499,8 +499,6 @@ void SparseLU::factorize(const MatrixType& matrix) eigen_assert(m_analysisIsOk && "analyzePattern() should be called first"); eigen_assert((matrix.rows() == matrix.cols()) && "Only for squared matrices"); - typedef typename IndexVector::Scalar StorageIndex; - m_isInitialized = true; diff --git a/eigenlib/Eigen/src/SparseQR/SparseQR.h b/eigenlib/Eigen/src/SparseQR/SparseQR.h index 2d4498b0..7409fcae 100644 --- a/eigenlib/Eigen/src/SparseQR/SparseQR.h +++ b/eigenlib/Eigen/src/SparseQR/SparseQR.h @@ -52,7 +52,7 @@ namespace internal { * rank-revealing permutations. Use colsPermutation() to get it. * * Q is the orthogonal matrix represented as products of Householder reflectors. - * Use matrixQ() to get an expression and matrixQ().transpose() to get the transpose. + * Use matrixQ() to get an expression and matrixQ().adjoint() to get the adjoint. * You can then apply it to a vector. * * R is the sparse triangular or trapezoidal matrix. The later occurs when A is rank-deficient. @@ -65,6 +65,7 @@ namespace internal { * \implsparsesolverconcept * * \warning The input sparse matrix A must be in compressed mode (see SparseMatrix::makeCompressed()). + * \warning For complex matrices matrixQ().transpose() will actually return the adjoint matrix. * */ template @@ -196,9 +197,9 @@ class SparseQR : public SparseSolverBase > Index rank = this->rank(); - // Compute Q^T * b; + // Compute Q^* * b; typename Dest::PlainObject y, b; - y = this->matrixQ().transpose() * B; + y = this->matrixQ().adjoint() * B; b = y; // Solve with the triangular matrix R @@ -604,7 +605,7 @@ struct SparseQR_QProduct : ReturnByValue @@ -668,13 +672,14 @@ struct SparseQRMatrixQReturnType : public EigenBase(m_qr,other.derived(),false); } + // To use for operations with the adjoint of Q SparseQRMatrixQTransposeReturnType adjoint() const { return SparseQRMatrixQTransposeReturnType(m_qr); } inline Index rows() const { return m_qr.rows(); } - inline Index cols() const { return (std::min)(m_qr.rows(),m_qr.cols()); } - // To use for operations with the transpose of Q + inline Index cols() const { return m_qr.rows(); } + // To use for operations with the transpose of Q FIXME this is the same as adjoint at the moment SparseQRMatrixQTransposeReturnType transpose() const { return SparseQRMatrixQTransposeReturnType(m_qr); @@ -682,6 +687,7 @@ struct SparseQRMatrixQReturnType : public EigenBase struct SparseQRMatrixQTransposeReturnType { @@ -712,7 +718,7 @@ struct Assignment, internal: typedef typename DstXprType::StorageIndex StorageIndex; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) { - typename DstXprType::PlainObject idMat(src.m_qr.rows(), src.m_qr.rows()); + typename DstXprType::PlainObject idMat(src.rows(), src.cols()); idMat.setIdentity(); // Sort the sparse householder reflectors if needed const_cast(&src.m_qr)->_sort_matrix_Q(); diff --git a/eigenlib/Eigen/src/StlSupport/StdDeque.h b/eigenlib/Eigen/src/StlSupport/StdDeque.h index cf1fedf9..af158f42 100644 --- a/eigenlib/Eigen/src/StlSupport/StdDeque.h +++ b/eigenlib/Eigen/src/StlSupport/StdDeque.h @@ -98,8 +98,10 @@ namespace std { { return deque_base::insert(position,x); } void insert(const_iterator position, size_type new_size, const value_type& x) { deque_base::insert(position, new_size, x); } -#elif defined(_GLIBCXX_DEQUE) && EIGEN_GNUC_AT_LEAST(4,2) +#elif defined(_GLIBCXX_DEQUE) && EIGEN_GNUC_AT_LEAST(4,2) && !EIGEN_GNUC_AT_LEAST(10, 1) // workaround GCC std::deque implementation + // GCC 10.1 doesn't let us access _Deque_impl _M_impl anymore and we have to + // fall-back to the default case void resize(size_type new_size, const value_type& x) { if (new_size < deque_base::size()) @@ -108,7 +110,7 @@ namespace std { deque_base::insert(deque_base::end(), new_size - deque_base::size(), x); } #else - // either GCC 4.1 or non-GCC + // either non-GCC or GCC between 4.1 and 10.1 // default implementation which should always work. void resize(size_type new_size, const value_type& x) { diff --git a/eigenlib/Eigen/src/StlSupport/details.h b/eigenlib/Eigen/src/StlSupport/details.h index e42ec024..2cfd13e0 100644 --- a/eigenlib/Eigen/src/StlSupport/details.h +++ b/eigenlib/Eigen/src/StlSupport/details.h @@ -22,13 +22,13 @@ namespace Eigen { class aligned_allocator_indirection : public EIGEN_ALIGNED_ALLOCATOR { public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; template struct rebind diff --git a/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h b/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h index 50a69f30..7261c7d0 100644 --- a/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h +++ b/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h @@ -297,8 +297,8 @@ SluMatrix asSluMatrix(MatrixType& mat) template MappedSparseMatrix map_superlu(SluMatrix& sluMat) { - eigen_assert((Flags&RowMajor)==RowMajor && sluMat.Stype == SLU_NR - || (Flags&ColMajor)==ColMajor && sluMat.Stype == SLU_NC); + eigen_assert(((Flags&RowMajor)==RowMajor && sluMat.Stype == SLU_NR) + || ((Flags&ColMajor)==ColMajor && sluMat.Stype == SLU_NC)); Index outerSize = (Flags&RowMajor)==RowMajor ? sluMat.ncol : sluMat.nrow; diff --git a/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h b/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h index dc74de93..91c09ab1 100644 --- a/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h +++ b/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h @@ -10,19 +10,37 @@ #ifndef EIGEN_UMFPACKSUPPORT_H #define EIGEN_UMFPACKSUPPORT_H -namespace Eigen { +namespace Eigen { /* TODO extract L, extract U, compute det, etc... */ // generic double/complex wrapper functions: -inline void umfpack_defaults(double control[UMFPACK_CONTROL], double) +inline void umfpack_defaults(double control[UMFPACK_CONTROL], double) { umfpack_di_defaults(control); } -inline void umfpack_defaults(double control[UMFPACK_CONTROL], std::complex) +inline void umfpack_defaults(double control[UMFPACK_CONTROL], std::complex) { umfpack_zi_defaults(control); } +inline void umfpack_report_info(double control[UMFPACK_CONTROL], double info[UMFPACK_INFO], double) +{ umfpack_di_report_info(control, info);} + +inline void umfpack_report_info(double control[UMFPACK_CONTROL], double info[UMFPACK_INFO], std::complex) +{ umfpack_zi_report_info(control, info);} + +inline void umfpack_report_status(double control[UMFPACK_CONTROL], int status, double) +{ umfpack_di_report_status(control, status);} + +inline void umfpack_report_status(double control[UMFPACK_CONTROL], int status, std::complex) +{ umfpack_zi_report_status(control, status);} + +inline void umfpack_report_control(double control[UMFPACK_CONTROL], double) +{ umfpack_di_report_control(control);} + +inline void umfpack_report_control(double control[UMFPACK_CONTROL], std::complex) +{ umfpack_zi_report_control(control);} + inline void umfpack_free_numeric(void **Numeric, double) { umfpack_di_free_numeric(Numeric); *Numeric = 0; } @@ -156,6 +174,7 @@ class UmfPackLU : public SparseSolverBase > public: typedef Array UmfpackControl; + typedef Array UmfpackInfo; UmfPackLU() : m_dummy(0,0), mp_matrix(m_dummy) @@ -215,7 +234,7 @@ class UmfPackLU : public SparseSolverBase > return m_q; } - /** Computes the sparse Cholesky decomposition of \a matrix + /** Computes the sparse Cholesky decomposition of \a matrix * Note that the matrix should be column-major, and in compressed format for best performance. * \sa SparseMatrix::makeCompressed(). */ @@ -240,7 +259,7 @@ class UmfPackLU : public SparseSolverBase > { if(m_symbolic) umfpack_free_symbolic(&m_symbolic,Scalar()); if(m_numeric) umfpack_free_numeric(&m_numeric,Scalar()); - + grab(matrix.derived()); analyzePattern_impl(); @@ -267,7 +286,7 @@ class UmfPackLU : public SparseSolverBase > { return m_control; } - + /** Provides access to the control settings array used by UmfPack. * * If this array contains NaN's, the default values are used. @@ -278,7 +297,7 @@ class UmfPackLU : public SparseSolverBase > { return m_control; } - + /** Performs a numeric decomposition of \a matrix * * The given matrix must has the same sparcity than the matrix on which the pattern anylysis has been performed. @@ -293,10 +312,38 @@ class UmfPackLU : public SparseSolverBase > umfpack_free_numeric(&m_numeric,Scalar()); grab(matrix.derived()); - + factorize_impl(); } + /** Prints the current UmfPack control settings. + * + * \sa umfpackControl() + */ + void umfpackReportControl() + { + umfpack_report_control(m_control.data(), Scalar()); + } + + /** Prints statistics collected by UmfPack. + * + * \sa analyzePattern(), compute() + */ + void umfpackReportInfo() + { + eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()"); + umfpack_report_info(m_control.data(), m_umfpackInfo.data(), Scalar()); + } + + /** Prints the status of the previous factorization operation performed by UmfPack (symbolic or numerical factorization). + * + * \sa analyzePattern(), compute() + */ + void umfpackReportStatus() { + eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()"); + umfpack_report_status(m_control.data(), m_fact_errorCode, Scalar()); + } + /** \internal */ template bool _solve_impl(const MatrixBase &b, MatrixBase &x) const; @@ -314,41 +361,42 @@ class UmfPackLU : public SparseSolverBase > m_numeric = 0; m_symbolic = 0; m_extractedDataAreDirty = true; + + umfpack_defaults(m_control.data(), Scalar()); } - + void analyzePattern_impl() { - umfpack_defaults(m_control.data(), Scalar()); - int errorCode = 0; - errorCode = umfpack_symbolic(internal::convert_index(mp_matrix.rows()), - internal::convert_index(mp_matrix.cols()), - mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - &m_symbolic, m_control.data(), 0); + m_fact_errorCode = umfpack_symbolic(internal::convert_index(mp_matrix.rows()), + internal::convert_index(mp_matrix.cols()), + mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), + &m_symbolic, m_control.data(), m_umfpackInfo.data()); m_isInitialized = true; - m_info = errorCode ? InvalidInput : Success; + m_info = m_fact_errorCode ? InvalidInput : Success; m_analysisIsOk = true; m_factorizationIsOk = false; m_extractedDataAreDirty = true; } - + void factorize_impl() { + m_fact_errorCode = umfpack_numeric(mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - m_symbolic, &m_numeric, m_control.data(), 0); + m_symbolic, &m_numeric, m_control.data(), m_umfpackInfo.data()); m_info = m_fact_errorCode == UMFPACK_OK ? Success : NumericalIssue; m_factorizationIsOk = true; m_extractedDataAreDirty = true; } - + template void grab(const EigenBase &A) { mp_matrix.~UmfpackMatrixRef(); ::new (&mp_matrix) UmfpackMatrixRef(A.derived()); } - + void grab(const UmfpackMatrixRef &A) { if(&(A.derived()) != &mp_matrix) @@ -357,19 +405,20 @@ class UmfPackLU : public SparseSolverBase > ::new (&mp_matrix) UmfpackMatrixRef(A); } } - + // cached data to reduce reallocation, etc. mutable LUMatrixType m_l; int m_fact_errorCode; UmfpackControl m_control; - + mutable UmfpackInfo m_umfpackInfo; + mutable LUMatrixType m_u; mutable IntColVectorType m_p; mutable IntRowVectorType m_q; UmfpackMatrixType m_dummy; UmfpackMatrixRef mp_matrix; - + void* m_numeric; void* m_symbolic; @@ -377,7 +426,7 @@ class UmfPackLU : public SparseSolverBase > int m_factorizationIsOk; int m_analysisIsOk; mutable bool m_extractedDataAreDirty; - + private: UmfPackLU(const UmfPackLU& ) { } }; @@ -427,7 +476,7 @@ bool UmfPackLU::_solve_impl(const MatrixBase &b, MatrixBas eigen_assert((BDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major rhs yet"); eigen_assert((XDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major result yet"); eigen_assert(b.derived().data() != x.derived().data() && " Umfpack does not support inplace solve"); - + int errorCode; Scalar* x_ptr = 0; Matrix x_tmp; @@ -442,7 +491,7 @@ bool UmfPackLU::_solve_impl(const MatrixBase &b, MatrixBas x_ptr = &x.col(j).coeffRef(0); errorCode = umfpack_solve(UMFPACK_A, mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - x_ptr, &b.const_cast_derived().col(j).coeffRef(0), m_numeric, m_control.data(), 0); + x_ptr, &b.const_cast_derived().col(j).coeffRef(0), m_numeric, m_control.data(), m_umfpackInfo.data()); if(x.innerStride()!=1) x.col(j) = x_tmp; if (errorCode!=0) diff --git a/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h index 1f8a531a..05a7449b 100644 --- a/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h +++ b/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h @@ -119,7 +119,7 @@ OP(const Scalar& s) const { \ return this->OP(Derived::PlainObject::Constant(rows(), cols(), s)); \ } \ EIGEN_DEVICE_FUNC friend EIGEN_STRONG_INLINE const RCmp ## COMPARATOR ## ReturnType \ -OP(const Scalar& s, const Derived& d) { \ +OP(const Scalar& s, const EIGEN_CURRENT_STORAGE_BASE_CLASS& d) { \ return Derived::PlainObject::Constant(d.rows(), d.cols(), s).OP(d); \ } diff --git a/eigenlib/howto.txt b/eigenlib/howto.txt index 5f893409..99b20682 100644 --- a/eigenlib/howto.txt +++ b/eigenlib/howto.txt @@ -3,11 +3,12 @@ Current Eigen Version 3.2.1 (26.02.2014) updated on 14/05/2014 Current Eigen Version 3.2.2 (04.08.2014) updated on 21/10/2014 Current Eigen Version 3.2.5 (16.06.2015) updated on 24/09/2015 Current Eigen Version 3.3.2 (18.01.2017) updated on 24/01/2017 +Current Eigen Version 3.3.9 (04.12.2020) updated on 15/06/2021 To update the lib: - download Eigen - unzip it somewhere -- delete (in the filesystem) the content of the folder eigenlib/Eigen - copy the folders 'Eigen' there +- delete (in the filesystem) the content of the folder eigenlib/Eigen - copy the folders 'Eigen' there - check the git status. - update this file - commit everything From 721dace0c5882c7c70ff3ea55fe0cb8aabd9553e Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 17 Jun 2021 12:49:42 +0200 Subject: [PATCH 130/140] update cmake to be sure vcg is included just one time --- CMakeLists.txt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 663c74cf..acc67cd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -279,14 +279,18 @@ set(SOURCES ) if (VCG_HEADER_ONLY) - add_library(vcglib INTERFACE) - target_include_directories( - vcglib INTERFACE - ${CMAKE_CURRENT_LIST_DIR} - ${EIGEN_INCLUDE_DIRS}) + if (NOT TARGET vcglib) # to be sure that vcglib target is created just one time + add_library(vcglib INTERFACE) + target_include_directories( + vcglib INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${EIGEN_INCLUDE_DIRS}) - #just to show headers in ide - add_custom_target(vcglib_ide SOURCES ${VCG_HEADERS}) + #just to show headers in ide + add_custom_target(vcglib_ide SOURCES ${VCG_HEADERS}) + else() + message(STATUS "- VCGLib - jumped - already included") + endif() else() #TODO make vcglib that includes all the wrap sources, checking everytime # if the the required targets (e.g. qt, gl, glew...) exists From ab3b3b3c5a38c298c716c60afbfe16e53eb6f251 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Mon, 21 Jun 2021 11:25:51 +0200 Subject: [PATCH 131/140] code cleanups - remove unneeded semicolons --- vcg/complex/algorithms/create/platonic.h | 4 ++-- vcg/complex/used_types.h | 2 +- vcg/space/intersection3.h | 4 ++-- vcg/space/tetra3.h | 4 ++-- wrap/gl/deprecated_space.h | 6 +++--- wrap/system/memory_info.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/vcg/complex/algorithms/create/platonic.h b/vcg/complex/algorithms/create/platonic.h index 8b4d906e..386bcff1 100644 --- a/vcg/complex/algorithms/create/platonic.h +++ b/vcg/complex/algorithms/create/platonic.h @@ -639,11 +639,11 @@ void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, i template static ScalarType _SQfnC(ScalarType a, ScalarType b){ return math::Sgn(cos(a))*pow(fabs(cos(a)),b); -}; +} template static ScalarType _SQfnS(ScalarType a, ScalarType b){ return math::Sgn(sin(a))*pow(fabs(sin(a)),b); -}; +} /** diff --git a/vcg/complex/used_types.h b/vcg/complex/used_types.h index 570dd1ce..61060a2b 100755 --- a/vcg/complex/used_types.h +++ b/vcg/complex/used_types.h @@ -119,6 +119,6 @@ struct _Face : public Face<_UsedTypes>{}; struct _Tetra : public TetraSimp<_UsedTypes>{}; struct _HEdge : public HEdge<_UsedTypes>{}; -}; +} #endif // USED_TYPES_H diff --git a/vcg/space/intersection3.h b/vcg/space/intersection3.h index e6cc96ae..e0fcadd2 100644 --- a/vcg/space/intersection3.h +++ b/vcg/space/intersection3.h @@ -121,7 +121,7 @@ namespace vcg { solution_count++; } return solution_count; - }; // end of IntersectionSegmentSphere + } // end of IntersectionSegmentSphere /*! @@ -214,7 +214,7 @@ namespace vcg { penetration_detected = (witness.SquaredNorm() <= (radius*radius)); witness += center; return penetration_detected; - }; //end of IntersectionSphereTriangle + } //end of IntersectionSphereTriangle /// intersection between line and plane template diff --git a/vcg/space/tetra3.h b/vcg/space/tetra3.h index cd702b31..4f07b145 100644 --- a/vcg/space/tetra3.h +++ b/vcg/space/tetra3.h @@ -379,7 +379,7 @@ class Tetra CoordType n1 = ((p2 - p0) ^ (p1 - p0)).normalized(); return M_PI - double(acos(n0 * n1)); - }; + } template static typename TetraType::ScalarType SolidAngle(const TetraType &t, const size_t vidx) @@ -390,7 +390,7 @@ class Tetra ScalarType a2 = DihedralAngle(t, Tetra::EofV(vidx, 2)); return (a0 + a1 + a2) - M_PI; - }; + } template static typename TetraType::ScalarType AspectRatio(const TetraType &t) diff --git a/wrap/gl/deprecated_space.h b/wrap/gl/deprecated_space.h index 563032cc..7478b859 100644 --- a/wrap/gl/deprecated_space.h +++ b/wrap/gl/deprecated_space.h @@ -152,7 +152,7 @@ namespace vcg { glVertex3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); glEnd(); glPopAttrib(); -}; +} template /// Funzione di utilita' per la visualizzazione in OpenGL (flat shaded) inline void glBoxFlat(Box3 const & b) @@ -190,7 +190,7 @@ inline void glBoxFlat(Box3 const & b) glVertex3f(b.min[0], b.min[1], b.max[2]); glEnd(); glPopAttrib(); -}; +} template @@ -228,7 +228,7 @@ inline void glBoxClip(const Box3 & b) glEnd(); glPopAttrib(); -}; +} template inline void glPlane3( Plane3 p, Point3 c, T size ) { Point3 w = p.Direction(); diff --git a/wrap/system/memory_info.h b/wrap/system/memory_info.h index 517f49e7..884ccc31 100644 --- a/wrap/system/memory_info.h +++ b/wrap/system/memory_info.h @@ -112,6 +112,6 @@ namespace vcg return (_currentfreememory >= mem); } }; -}; +} -#endif \ No newline at end of file +#endif From b2727b1394fc242079ca819d1858ad4de774d662 Mon Sep 17 00:00:00 2001 From: Luigi Malomo Date: Fri, 25 Jun 2021 19:29:46 +0200 Subject: [PATCH 132/140] warnings fixed --- vcg/complex/append.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 2d342038..1f064611 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -410,7 +410,7 @@ static void MeshAppendConst( if(adjFlag) ImportVertexAdj(ml,mr,vl,v,remap); if (vertTexFlag){ - if (v.T().n() < mappingTextures.size()) { + if (size_t(v.T().n()) < mappingTextures.size()) { //standard case: the texture is contained in the mesh vl.T().n() = mappingTextures[v.T().n()]; } @@ -452,7 +452,7 @@ static void MeshAppendConst( fl.ImportData(f); if(wedgeTexFlag) { for(int i = 0; i < fl.VN(); ++i){ - if (f.WT(i).n() < mappingTextures.size()){ + if (size_t(f.WT(i).n()) < mappingTextures.size()){ //standard case: the texture is contained in the mesh fl.WT(i).n() = mappingTextures[f.WT(i).n()]; } From 094918662bb7819332f2d2b3f7986a7ec62ecdf7 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Mon, 5 Jul 2021 13:02:13 +0200 Subject: [PATCH 133/140] fix append texcoords --- vcg/complex/append.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 1f064611..bba38581 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -400,8 +400,10 @@ static void MeshAppendConst( // phase 2. // copy data from mr to its corresponding elements in ml and adjacencies + //vtexcoords - can copy only if they are enabled both on l and r + bool vertTexFlag = HasPerVertexTexCoord(ml) && HasPerVertexTexCoord(mr); + // vertex - bool vertTexFlag = HasPerVertexTexCoord(mr); ForEachVertex(mr, [&](const VertexRight& v) { if(!selected || v.IsS()){ @@ -437,8 +439,10 @@ static void MeshAppendConst( } }); + //ftexcoords - can copy only if they are enabled both on l and r + bool wedgeTexFlag = HasPerWedgeTexCoord(ml) && HasPerWedgeTexCoord(mr); + // face - bool wedgeTexFlag = HasPerWedgeTexCoord(mr); ForEachFace(mr, [&](const FaceRight& f) { if(!selected || f.IsS()) From 0f320aa6710d60e2940432d07757ef91d835e19c Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 6 Jul 2021 16:43:22 +0200 Subject: [PATCH 134/140] fix off polygon export --- vcg/complex/algorithms/polygon_support.h | 7 +++++-- wrap/io_trimesh/export_off.h | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/vcg/complex/algorithms/polygon_support.h b/vcg/complex/algorithms/polygon_support.h index bce0d219..801a35bb 100644 --- a/vcg/complex/algorithms/polygon_support.h +++ b/vcg/complex/algorithms/polygon_support.h @@ -24,6 +24,9 @@ #ifndef __VCGLIB_POLYGON_SUPPORT #define __VCGLIB_POLYGON_SUPPORT +#include +#include +#include #include #include @@ -141,8 +144,8 @@ namespace tri { { std::vector vs;// vertices of the polygon ExtractPolygon(&*tfi,vs); - if (vs.size() > 3) - std::reverse(vs.begin(), vs.end()); + if (vs.size() > 3) + std::reverse(vs.begin(), vs.end()); //now vs contains all the vertices of the polygon (still in the trimesh) if (vs.size()==0)continue; typename PolyMeshType::FaceIterator pfi = tri::Allocator::AddFaces(pm,1); diff --git a/wrap/io_trimesh/export_off.h b/wrap/io_trimesh/export_off.h index 3a9fec97..d4b8435b 100644 --- a/wrap/io_trimesh/export_off.h +++ b/wrap/io_trimesh/export_off.h @@ -104,10 +104,17 @@ public: tri::UpdateFlags::FaceClearV(m); for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if (!fi->IsD()) if (!fi->IsV()) { vcg::tri::PolygonSupport::ExtractPolygon(&*fi,polygon); + //not sure why this std::reverse is needed. ExtractPolygon is used in + //many other functions, and nobody complained. however, this list is + //clockwise wrt fi normal. + std::reverse(polygon.begin(), polygon.end()); if(!polygon.empty()) { fprintf(fpout,"%d ", int(polygon.size()) ); - for (size_t i=0; iFlags() ); + for (size_t i=0; iC()[0],fi->C()[1],fi->C()[2] ); fprintf(fpout,"\n"); } } From a282947a724a9aa251f80b57a01b65d62eef5777 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Wed, 7 Jul 2021 16:45:15 +0200 Subject: [PATCH 135/140] get birth faces indices in ImportFromPolyMesh function --- vcg/complex/algorithms/polygon_support.h | 91 ++++++++++++++---------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/vcg/complex/algorithms/polygon_support.h b/vcg/complex/algorithms/polygon_support.h index 801a35bb..84429259 100644 --- a/vcg/complex/algorithms/polygon_support.h +++ b/vcg/complex/algorithms/polygon_support.h @@ -74,46 +74,63 @@ namespace tri { } } - /** - Import a trianglemesh from a polygon mesh - **/ - static void ImportFromPolyMesh(TriMeshType & tm, PolyMeshType & pm) - { - tri::RequirePolygonalMesh(pm); - std::vector points; + /** + * @brief Import a trianglemesh from a polygon mesh + * @param tm: output triangle mesh + * @param pm: input polygonal mesh + * @param birthFaces: a mapping that tells, for each face of the triangle mesh, + * which one is its birth face in the polygonal mesh. + */ + static void ImportFromPolyMesh(TriMeshType& tm, PolyMeshType& pm, std::vector& birthFaces) + { + birthFaces.clear(); + birthFaces.reserve(pm.FN()); //at least the same face number of the polymesh + tri::RequirePolygonalMesh(pm); + std::vector points; - // the vertices are the same, simply import them - PolyVertexIterator vi; - TriVertexIterator tvi = Allocator::AddVertices(tm,pm.vert.size()); - int cnt = 0; - for(tvi = tm.vert.begin(),vi = pm.vert.begin(); tvi != tm.vert.end(); ++tvi,++vi,++cnt) - if(!(*vi).IsD()) (*tvi).ImportData(*vi); else tri::Allocator::DeleteVertex(tm,(*tvi)); + // the vertices are the same, simply import them + PolyVertexIterator vi; + TriVertexIterator tvi = Allocator::AddVertices(tm,pm.vert.size()); + int cnt = 0; + for(tvi = tm.vert.begin(),vi = pm.vert.begin(); tvi != tm.vert.end(); ++tvi,++vi,++cnt) + if(!(*vi).IsD()) (*tvi).ImportData(*vi); else tri::Allocator::DeleteVertex(tm,(*tvi)); - for(PolyFaceIterator fi = pm.face.begin(); fi != pm.face.end(); ++fi) - { - if(!((*fi).IsD())){ - points.clear(); - for(int i = 0; i < (*fi).VN(); ++i) { - typename PolyMeshType::VertexType * v = (*fi).V(i); - points.push_back(v->P()); - } - std::vector faces; - TessellatePlanarPolygon3(points,faces); - for(size_t i = 0; i::AddFace(tm, - tri::Index(pm,(*fi).V( faces[i+0] )), - tri::Index(pm,(*fi).V( faces[i+1] )), - tri::Index(pm,(*fi).V( faces[i+2] )) ); + for(PolyFaceIterator fi = pm.face.begin(); fi != pm.face.end(); ++fi) + { + if(!((*fi).IsD())){ + points.clear(); + for(int i = 0; i < (*fi).VN(); ++i) { + typename PolyMeshType::VertexType * v = (*fi).V(i); + points.push_back(v->P()); + } + std::vector faces; + TessellatePlanarPolygon3(points,faces); - tfi->ImportData(*fi); - // set the F flags - if( (faces[i ]+1)%points.size() != size_t(faces[i+1])) (*tfi).SetF(0); - if( (faces[i+1]+1)%points.size() != size_t(faces[i+2])) (*tfi).SetF(1); - if( (faces[i+2]+1)%points.size() != size_t(faces[i ])) (*tfi).SetF(2); - } - } - } - } + //all the faces we add in tm have as a birth face fi + birthFaces.insert(birthFaces.end(), faces.size()/3, tri::Index(pm, *fi)); + + for(size_t i = 0; i::AddFace( + tm, + tri::Index(pm,(*fi).V( faces[i+0] )), + tri::Index(pm,(*fi).V( faces[i+1] )), + tri::Index(pm,(*fi).V( faces[i+2] )) ); + + tfi->ImportData(*fi); + // set the F flags + if( (faces[i ]+1)%points.size() != size_t(faces[i+1])) (*tfi).SetF(0); + if( (faces[i+1]+1)%points.size() != size_t(faces[i+2])) (*tfi).SetF(1); + if( (faces[i+2]+1)%points.size() != size_t(faces[i ])) (*tfi).SetF(2); + } + } + } + } + + static void ImportFromPolyMesh(TriMeshType & tm, PolyMeshType & pm) + { + std::vector dummyVector; + ImportFromPolyMesh(tm, pm, dummyVector); + } /** From 735f93c256f960aa50ce3a0559c10b8eb1f2782a Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 8 Jul 2021 12:56:06 +0200 Subject: [PATCH 136/140] fix load obj texture filename when has any option --- wrap/io_trimesh/import_obj.h | 260 +++++++++++++++++------------------ 1 file changed, 130 insertions(+), 130 deletions(-) diff --git a/wrap/io_trimesh/import_obj.h b/wrap/io_trimesh/import_obj.h index 66ce8526..0a3a6347 100644 --- a/wrap/io_trimesh/import_obj.h +++ b/wrap/io_trimesh/import_obj.h @@ -960,136 +960,136 @@ public: return ret; } - static bool LoadMaterials(const char * filename, std::vector &materials, std::vector &textures) - { - // assumes we are in the right directory - - std::ifstream stream(filename); - if (stream.fail()) - return false; - - std::vector< std::string > tokens; - std::string line; - std::string header; - - materials.clear(); - Material currentMaterial; - - // Fill in some default values for the material - currentMaterial.index = (unsigned int)(-1); - currentMaterial.Ka = Point3f(0.2, 0.2, 0.2); - currentMaterial.Kd = Point3f(1, 1, 1); - currentMaterial.Ks = Point3f(1, 1, 1); - currentMaterial.Tr = 1; - currentMaterial.Ns = 0; - currentMaterial.illum = 2; - - bool first = true; - while (!stream.eof()) - { - tokens.clear(); - TokenizeNextLine(stream, tokens, line, 0); - - if (tokens.size() > 0) - { - header.clear(); - header = tokens[0]; - - if (header.compare("newmtl")==0) - { - if (!first) - { - materials.push_back(currentMaterial); - currentMaterial = Material(); - currentMaterial.index = (unsigned int)(-1); - } - else - first = false; - //strcpy(currentMaterial.name, tokens[1].c_str()); - if(tokens.size() < 2) - return false; - else if (tokens.size() == 2) - currentMaterial.materialName = tokens[1]; //play it safe - else - currentMaterial.materialName = line.substr(7); //space in the name, get everything after "newmtl " - } - else if (header.compare("Ka")==0) - { - if (tokens.size() < 4) return false; - currentMaterial.Ka = Point3fFrom3Tokens(tokens,1); - } - else if (header.compare("Kd")==0) - { - if (tokens.size() < 4) return false; - currentMaterial.Kd = Point3fFrom3Tokens(tokens,1); - } - else if (header.compare("Ks")==0) - { - if (tokens.size() < 4) return false; - currentMaterial.Ks = Point3fFrom3Tokens(tokens,1); - } - else if ( (header.compare("d")==0) || - (header.compare("Tr")==0) ) // alpha - { - if (tokens.size() < 2) return false; - currentMaterial.Tr = (float) atof(tokens[1].c_str()); - } - else if (header.compare("Ns")==0) // shininess - { - if (tokens.size() < 2) return false; - currentMaterial.Ns = float(atoi(tokens[1].c_str())); - } - else if (header.compare("illum")==0) // specular illumination on/off - { - if (tokens.size() < 2) return false; - currentMaterial.illum = atoi(tokens[1].c_str());; - } - else if(header.compare("map_Kd")==0) // texture name - { - std::string textureName; - if (tokens.size() < 2) - return false; - else if (tokens.size() == 2) - textureName = tokens[1]; //play it safe - else - textureName = line.substr(7); //get everything after "map_Kd " - - currentMaterial.map_Kd=textureName; - - // adding texture name into textures vector (if not already present) - // avoid adding the same name twice - auto it = std::find(textures.begin(), textures.end(), textureName); - if(it==textures.end()) { - currentMaterial.index = textures.size(); - textures.push_back(textureName); - } else { - currentMaterial.index = std::distance(textures.begin(),it); - } - } - // we simply ignore other situations - } - } - materials.push_back(currentMaterial); // add last read material - - stream.close(); - // Sometimes some materials have texture and no texture - // in this case for sake of uniformity we just use the first texture. - if(!textures.empty()) - { - for(size_t i=0;i &materials, std::vector &textures) + { + // assumes we are in the right directory + + std::ifstream stream(filename); + if (stream.fail()) + return false; + + std::vector< std::string > tokens; + std::string line; + std::string header; + + materials.clear(); + Material currentMaterial; + + // Fill in some default values for the material + currentMaterial.index = (unsigned int)(-1); + currentMaterial.Ka = Point3f(0.2, 0.2, 0.2); + currentMaterial.Kd = Point3f(1, 1, 1); + currentMaterial.Ks = Point3f(1, 1, 1); + currentMaterial.Tr = 1; + currentMaterial.Ns = 0; + currentMaterial.illum = 2; + + bool first = true; + while (!stream.eof()) + { + tokens.clear(); + TokenizeNextLine(stream, tokens, line, 0); + + if (tokens.size() > 0) + { + header.clear(); + header = tokens[0]; + + if (header.compare("newmtl")==0) + { + if (!first) + { + materials.push_back(currentMaterial); + currentMaterial = Material(); + currentMaterial.index = (unsigned int)(-1); + } + else + first = false; + //strcpy(currentMaterial.name, tokens[1].c_str()); + if(tokens.size() < 2) + return false; + else if (tokens.size() == 2) + currentMaterial.materialName = tokens[1]; //play it safe + else + currentMaterial.materialName = line.substr(7); //space in the name, get everything after "newmtl " + } + else if (header.compare("Ka")==0) + { + if (tokens.size() < 4) return false; + currentMaterial.Ka = Point3fFrom3Tokens(tokens,1); + } + else if (header.compare("Kd")==0) + { + if (tokens.size() < 4) return false; + currentMaterial.Kd = Point3fFrom3Tokens(tokens,1); + } + else if (header.compare("Ks")==0) + { + if (tokens.size() < 4) return false; + currentMaterial.Ks = Point3fFrom3Tokens(tokens,1); + } + else if ( (header.compare("d")==0) || + (header.compare("Tr")==0) ) // alpha + { + if (tokens.size() < 2) return false; + currentMaterial.Tr = (float) atof(tokens[1].c_str()); + } + else if (header.compare("Ns")==0) // shininess + { + if (tokens.size() < 2) return false; + currentMaterial.Ns = float(atoi(tokens[1].c_str())); + } + else if (header.compare("illum")==0) // specular illumination on/off + { + if (tokens.size() < 2) return false; + currentMaterial.illum = atoi(tokens[1].c_str());; + } + else if(header.compare("map_Kd")==0) // texture name + { + std::string textureName; + if (tokens.size() < 2) + return false; + else { + //the tex name is the last one (after any option) + textureName = tokens[tokens.size()-1]; + } + + currentMaterial.map_Kd=textureName; + + // adding texture name into textures vector (if not already present) + // avoid adding the same name twice + auto it = std::find(textures.begin(), textures.end(), textureName); + if(it==textures.end()) { + currentMaterial.index = textures.size(); + textures.push_back(textureName); + } else { + currentMaterial.index = std::distance(textures.begin(),it); + } + } + // we simply ignore other situations + } + } + materials.push_back(currentMaterial); // add last read material + + stream.close(); + // Sometimes some materials have texture and no texture + // in this case for sake of uniformity we just use the first texture. + if(!textures.empty()) + { + for(size_t i=0;i Date: Fri, 9 Jul 2021 12:23:05 +0200 Subject: [PATCH 137/140] TriMesh virtual destructor and fix TriMesh clean --- vcg/complex/base.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 88de7028..2656a318 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -443,7 +443,7 @@ public: } /// destructor - ~TriMesh() + virtual ~TriMesh() { // ClearAttributes(); Clear(); @@ -481,13 +481,14 @@ public: face.clear(); edge.clear(); tetra.clear(); - // textures.clear(); - // normalmaps.clear(); + textures.clear(); + normalmaps.clear(); vn = 0; en = 0; fn = 0; hn = 0; tn = 0; + attrn = 0; imark = 0; C()=Color4b::Gray; } From cfe0511f35a994967ac19501484b47b6d05b0fdc Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 13 Jul 2021 12:36:04 +0200 Subject: [PATCH 138/140] const getFovFromFocal in shot.h --- vcg/math/shot.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcg/math/shot.h b/vcg/math/shot.h index 0eeda9cf..6ab6def0 100644 --- a/vcg/math/shot.h +++ b/vcg/math/shot.h @@ -127,7 +127,7 @@ public: void SetViewPoint(const vcg::Point3 & viewpoint); /// GET fov from focal - float GetFovFromFocal(); + float GetFovFromFocal() const; /// look at (point+up) void LookAt(const vcg::Point3 & point,const vcg::Point3 & up); @@ -256,7 +256,7 @@ void Shot::SetViewPoint(const vcg::Point3 & viewpoint) /// GET fov from focal template -float Shot::GetFovFromFocal() +float Shot::GetFovFromFocal() const { double viewportYMm= Intrinsics.PixelSizeMm[1]* Intrinsics.ViewportPx[1]; return 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*Intrinsics.FocalMm)))); From f1530c585b953b05869b42de3bf3a1b7918a284b Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Tue, 13 Jul 2021 16:46:02 +0200 Subject: [PATCH 139/140] wrap/gl camera and shot const correctness --- wrap/gl/camera.h | 30 +++++++++++++++--------------- wrap/gl/shot.h | 8 ++++---- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/wrap/gl/camera.h b/wrap/gl/camera.h index a72d15d4..debf7252 100644 --- a/wrap/gl/camera.h +++ b/wrap/gl/camera.h @@ -139,35 +139,35 @@ static void SetGLIsometricProj(float x1, float x2, float y1, float y2, float z1, } /// get OpenGL-like frustum from a vcg camera (intrinsics) -static void GetFrustum(vcg::Camera & intrinsics, S & sx,S & dx,S & bt,S & tp,S & f) +static void GetFrustum(const vcg::Camera & intrinsics, S & sx,S & dx,S & bt,S & tp,S & f) { intrinsics.GetFrustum(sx,dx,bt,tp,f); } /// set the OpenGL PROJECTION matrix to match the camera (intrinsics). requires near and far plane -static void TransformGL(vcg::Camera & camera, S nearDist, S farDist ) +static void TransformGL(const vcg::Camera & camera, S nearDist, S farDist ) { S sx,dx,bt,tp,nr; camera.GetFrustum(sx,dx,bt,tp,nr); - if(camera.cameraType == CameraType::PERSPECTIVE) { - S ratio = nearDist/nr; - sx *= ratio; - dx *= ratio; - bt *= ratio; - tp *= ratio; - } + if(camera.cameraType == CameraType::PERSPECTIVE) { + S ratio = nearDist/nr; + sx *= ratio; + dx *= ratio; + bt *= ratio; + tp *= ratio; + } assert(glGetError()==0); - switch(camera.cameraType) + switch(camera.cameraType) { - case CameraType::PERSPECTIVE: glFrustum(sx,dx,bt,tp,nearDist,farDist); break; - case CameraType::ORTHO: glOrtho(sx,dx,bt,tp,nearDist,farDist); break; - case CameraType::ISOMETRIC: SetGLIsometricProj(sx,dx,bt,tp,nearDist,farDist); break; - case CameraType::CAVALIERI: SetGLCavalieriProj(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::PERSPECTIVE: glFrustum(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::ORTHO: glOrtho(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::ISOMETRIC: SetGLIsometricProj(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::CAVALIERI: SetGLCavalieriProj(sx,dx,bt,tp,nearDist,farDist); break; } - + assert(glGetError()==0); }; diff --git a/wrap/gl/shot.h b/wrap/gl/shot.h index b175c3d6..4f4baade 100644 --- a/wrap/gl/shot.h +++ b/wrap/gl/shot.h @@ -95,13 +95,13 @@ struct GlShot { typedef GlCamera GlCameraType; /// returns the OpenGL 4x4 MODELVIEW matrix that describes the shot position and orientation (extrinsics) -static void MatrixGL(ShotType & shot,vcg::Matrix44 & m) +static void MatrixGL(const ShotType & shot,vcg::Matrix44 & m) { m = shot.GetWorldToExtrinsicsMatrix(); } /// set the OpenGL MODELVIEW matrix to match the shot (extrinsics) -static void TransformGL(vcg::Shot & shot) +static void TransformGL(const vcg::Shot & shot) { vcg::Matrix44 m; MatrixGL(shot,m); @@ -109,7 +109,7 @@ static void TransformGL(vcg::Shot & shot) } /// set the OpenGL PROJECTION and MODELVIEW matrix to match camera+shot. requires near and far plane -static void SetView(vcg::Shot & shot, ScalarType nearDist, ScalarType farDist) +static void SetView(const vcg::Shot & shot, ScalarType nearDist, ScalarType farDist) { assert(glGetError() == 0); glMatrixMode(GL_PROJECTION); @@ -170,7 +170,7 @@ static ScalarType GetFarPlane(vcg::Shot & shot, vcg::Box3 & shot, vcg::Box3 bbox, ScalarType &nr, ScalarType &fr) +static void GetNearFarPlanes(const vcg::Shot & shot, vcg::Box3 bbox, ScalarType &nr, ScalarType &fr) { vcg::Point3 zaxis = shot.Axis(2); ScalarType offset = zaxis * shot.GetViewPoint(); From bc07a00def027222f6a78ddb7e95dc964c583e1c Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 15 Jul 2021 18:52:45 +0200 Subject: [PATCH 140/140] bugfix on edge rendering bo manager --- ..._mesh_attributes_multi_viewer_bo_manager.h | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 30feb0ef..e0fd053e 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include @@ -1158,25 +1158,27 @@ namespace vcg triangles += cit->second - cit->first + 1; } - if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) - { - for (typename std::vector::iterator it = _edge.begin(); it != _edge.end(); ++it) - { - it->_v[0] = vpatlas[it->_v[0]]; - it->_v[1] = vpatlas[it->_v[1]]; - } - - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_EDGEINDICES]; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, buffobj->_components * buffobj->getSizeOfGLType() * _edge.size(), &_edge[0]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) _texindnumtriangles[t] = std::make_pair(mit->first, triangles); ++t; } + if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) + { + unsigned int i = 0; + for (EdgeVertInd& e : _edge) + { + e._v[0] = vpatlas[e._v[0]]; + e._v[1] = vpatlas[e._v[1]]; + ++i; + } + + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_EDGEINDICES]; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, buffobj->_components * buffobj->getSizeOfGLType() * _edge.size(), &_edge[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + //return (k != tn) // throw MeshLabException("Mesh has not been properly partitioned"); return true;