From bf7cf6d5a08d8bb49294a5bd68203c59c785f5ef Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Fri, 16 Feb 2018 07:29:42 +0100 Subject: [PATCH] Added saving of per vertex point3 attribute. warning: it leaks memory... --- .../trimesh_attribute_saving.cpp | 26 ++++--- wrap/io_trimesh/io_ply.h | 68 +++++++++++++------ 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/apps/sample/trimesh_attribute_saving/trimesh_attribute_saving.cpp b/apps/sample/trimesh_attribute_saving/trimesh_attribute_saving.cpp index 2fcabd6f..7afe64ee 100644 --- a/apps/sample/trimesh_attribute_saving/trimesh_attribute_saving.cpp +++ b/apps/sample/trimesh_attribute_saving/trimesh_attribute_saving.cpp @@ -46,25 +46,33 @@ int main() { MyMesh m; Torus(m, 3.0f, 1.0f); - //! [Adding an attribute] + //! [Adding a few attributes] // add a per-vertex attribute with type float named "GaussianCurvature" MyMesh::PerVertexAttributeHandle - hv = vcg::tri::Allocator:: GetPerVertexAttribute (m,std::string("GaussianCurvature")); + hvf = vcg::tri::Allocator:: GetPerVertexAttribute (m,std::string("GaussianCurvature")); + + MyMesh::PerVertexAttributeHandle + hv3f = vcg::tri::Allocator:: GetPerVertexAttribute (m,std::string("InvertedNormal")); + // add a per-face attribute with type float named "FaceArea" MyMesh::PerFaceAttributeHandle - hf = vcg::tri::Allocator:: GetPerFaceAttribute (m,std::string("FaceArea")); + hff = vcg::tri::Allocator:: GetPerFaceAttribute (m,std::string("FaceArea")); //! [filling the attribute] - vcg::tri::Allocator::ClearPerVertexAttribute(m,hv, float(M_PI*2)); + vcg::tri::Allocator::ClearPerVertexAttribute(m,hvf, float(M_PI*2)); + vcg::tri::Allocator::ClearPerVertexAttribute(m,hv3f, vcg::Point3f(0,0,0)); ForEachFace(m, [&](MyFace &f){ - hf[&f]=vcg::DoubleArea(f)*0.5f; - for(int i=0;i<3;++i) - hv[f.V(i)] -= vcg::Angle(f.P1(i)-f.P0(i),f.P2(i)-f.P0(i)); + hff[&f]=vcg::DoubleArea(f)*0.5f; + for(int i=0;i<3;++i){ + hvf[f.V(i)] -= vcg::Angle(f.P1(i)-f.P0(i),f.P2(i)-f.P0(i)); + hv3f[f.V(i)] -= vcg::NormalizedTriangleNormal(f); + } }); - //! [Saving two attributes in ply, one of the two disguised as quality] + //! [Saving 3 attributes in ply, one of the 3 disguised as quality] vcg::tri::io::PlyInfo pi; pi.AddPerVertexFloatAttribute("GaussianCurvature","quality"); pi.AddPerFaceFloatAttribute("FaceArea"); - vcg::tri::io::ExporterPLY::Save(m,"MeshWithCurvature.ply",true,pi); + pi.AddPerVertexPoint3fAttribute(m,"InvertedNormal"); + vcg::tri::io::ExporterPLY::Save(m,"MeshWithCurvature.ply",false,pi); } diff --git a/wrap/io_trimesh/io_ply.h b/wrap/io_trimesh/io_ply.h index 08b75aad..1828a926 100644 --- a/wrap/io_trimesh/io_ply.h +++ b/wrap/io_trimesh/io_ply.h @@ -65,30 +65,58 @@ 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"}; + static std::vector *elemDescVec[2]={&(this->VertDescriptorVec), &(this->FaceDescriptorVec)}; + static std::vector *elemNameVec[2]={&(this->VertAttrNameVec), &(this->FaceAttrNameVec)}; + + 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=propName; + elemDescVec[elemType]->back().stotype1 = vcg::ply::T_FLOAT; + elemDescVec[elemType]->back().memtype1 = vcg::ply::T_FLOAT; + } - void AddPerVertexFloatAttribute(const std::string &attrName, std::string propName="") - { - static const char *vertStr="vertex"; - if(propName.empty()) propName=attrName; - VertDescriptorVec.push_back(PropDescriptor()); - VertAttrNameVec.push_back(attrName); - VertDescriptorVec.back().elemname=vertStr; - VertDescriptorVec.back().propname=propName.c_str(); - VertDescriptorVec.back().stotype1 = vcg::ply::T_FLOAT; - VertDescriptorVec.back().memtype1 = vcg::ply::T_FLOAT; + void AddPerVertexFloatAttribute(const char *attrName, const char *propName=0) { + AddPerElemFloatAttribute(0,attrName,propName); } - void AddPerFaceFloatAttribute(const std::string &attrName, std::string propName="") - { - static const char *faceStr="face"; - if(propName.empty()) propName=attrName; - FaceDescriptorVec.push_back(PropDescriptor()); - FaceAttrNameVec.push_back(attrName); - FaceDescriptorVec.back().elemname=faceStr; - FaceDescriptorVec.back().propname=propName.c_str(); - FaceDescriptorVec.back().stotype1 = vcg::ply::T_FLOAT; - FaceDescriptorVec.back().memtype1 = vcg::ply::T_FLOAT; + void AddPerFaceFloatAttribute(const char *attrName, const char *propName=0) { + 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="") + { + 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 + 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]; + }); + AddPerVertexFloatAttribute(attrxyz[i]); + } + } + + PlyInfo() { status=0;