diff --git a/vcg/complex/algorithms/create/platonic.h b/vcg/complex/algorithms/create/platonic.h index 8309c0e1..9d654e52 100644 --- a/vcg/complex/algorithms/create/platonic.h +++ b/vcg/complex/algorithms/create/platonic.h @@ -522,6 +522,47 @@ void Cone( MeshType& in, } } +template +void OrientedCone(MeshType & m, + const typename MeshType::CoordType origin, + const typename MeshType::CoordType end, + const typename MeshType::ScalarType r1, + const typename MeshType::ScalarType r2, + const int SubDiv = 36 ) +{ + typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::CoordType CoordType; + typedef Matrix44 Matrix44x; + Cone(m,r1,r2,Distance(origin,end),SubDiv); + +// tri::UpdatePosition::Translate(m,CoordType(0,1,0)); +// tri::UpdatePosition::Scale(m,CoordType(1,0.5f,1)); +// tri::UpdatePosition::Scale(m,CoordType(xScale,1.0f,yScale)); + +// float height = Distance(origin,end); +// tri::UpdatePosition::Scale(m,CoordType(radius,height,radius)); + CoordType norm = end-origin; + ScalarType angleRad = Angle(CoordType(0,1,0),norm); + const ScalarType Delta= 0.000000001; + Matrix44x rotM; + if (fabs(angleRad)::Matrix(m,rotM); + tri::UpdatePosition::Translate(m,origin); + +} + template void Box(MeshType &in, const typename MeshType::BoxType & bb ) @@ -1000,9 +1041,21 @@ void OrientedEllipticPrism(MeshType & m, const typename MeshType::CoordType orig tri::UpdatePosition::Scale(m,CoordType(radius,height,radius)); CoordType norm = end-origin; ScalarType angleRad = Angle(CoordType(0,1,0),norm); - CoordType axis = CoordType(0,1,0)^norm; + const ScalarType Delta= 0.000000001; Matrix44x rotM; - rotM.SetRotateRad(angleRad,axis); + if (fabs(angleRad)::Matrix(m,rotM); tri::UpdatePosition::Translate(m,origin); diff --git a/vcg/complex/algorithms/curve_on_manifold.h b/vcg/complex/algorithms/curve_on_manifold.h index e3dd412d..ea6135ef 100644 --- a/vcg/complex/algorithms/curve_on_manifold.h +++ b/vcg/complex/algorithms/curve_on_manifold.h @@ -129,6 +129,13 @@ public: return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP,closestN,ip); } + FaceType *GetClosestFaceIP(const CoordType &p, CoordType &ip, CoordType &in) + { + ScalarType closestDist; + CoordType closestP; + return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP,in,ip); + } + FaceType *GetClosestFacePoint(const CoordType &p, CoordType &closestP) { ScalarType closestDist; @@ -193,8 +200,10 @@ public: { VertexPointer v0 = FindVertexSnap(f0,ip0); VertexPointer v1 = FindVertexSnap(f1,ip1); + if(v0==0 || v1==0) return false; if(v0==v1) return false; + FacePointer ff0,ff1; int e0,e1; bool ret=face::FindSharedFaces(v0,v1,ff0,ff1,e0,e1); diff --git a/vcg/complex/algorithms/dual_meshing.h b/vcg/complex/algorithms/dual_meshing.h index 8d15673a..1a0f8ede 100644 --- a/vcg/complex/algorithms/dual_meshing.h +++ b/vcg/complex/algorithms/dual_meshing.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace vcg { namespace tri { @@ -61,65 +62,8 @@ class DualMeshing vertSeq.push_back(indexV); } - if (startV.IsB()) - { - vcg::face::Pos firstPos=posVec[0]; - firstPos.FlipE(); - assert(firstPos.IsBorder()); - - int indexVt0=vcg::tri::Index(primal,firstPos.V()); - int indexVt1=vcg::tri::Index(primal,firstPos.VFlip()); - std::pair key(std::min(indexVt0,indexVt1), - std::max(indexVt0,indexVt1)); - assert(EdgeMap.count(key)>0); - int indexV0=EdgeMap[key]; - - vcg::face::Pos lastPos=posVec.back(); - assert(lastPos.IsBorder()); - - indexVt0=vcg::tri::Index(primal,lastPos.V()); - indexVt1=vcg::tri::Index(primal,lastPos.VFlip()); - key=std::pair (std::min(indexVt0,indexVt1), - std::max(indexVt0,indexVt1)); - assert(EdgeMap.count(key)>0); - int indexV1=EdgeMap[key]; - - vertSeq.push_back(indexV1); - vertSeq.push_back(indexV0); - } } - static void CreateBorderEdgeVert(PolyMeshType &primal, - PolyMeshType &dual, - std::map, int> &VertMap) - { - VertMap.clear(); - vcg::tri::UpdateFlags::VertexClearB(primal); - - for (size_t i=0;iSetB(); - v1->SetB(); - - int V0Index=vcg::tri::Index(primal,v0); - int V1Index=vcg::tri::Index(primal,v1); - CoordType pos=(v0->P()+v1->P())/2; - vcg::tri::Allocator::AddVertex(dual,pos); - std::pair key(std::min(V0Index,V1Index), - std::max(V0Index,V1Index)); - - VertMap[key]=dual.vert.size()-1; - } - } static void CreateFaceVert(PolyMeshType &primal, PolyMeshType &dual, @@ -137,7 +81,6 @@ class DualMeshing int num=0; if (snapBorder)//search for border edge { - std::vector BorderPos; for (int j=0;jIsB())continue; @@ -145,7 +88,7 @@ class DualMeshing num++; } if (num>0) - pos/=num; + pos/=num; } if (num==0) @@ -153,15 +96,22 @@ class DualMeshing for (int j=0;jP(); - int indexV=vcg::tri::Index(primal,primal.face[i].V(j)); - if (VertFace[indexV]!=-1)continue; - VertFace[indexV]=i; } pos/=(ScalarType)primal.face[i].VN(); } vcg::tri::Allocator::AddVertex(dual,pos); VertMap[i]=dual.vert.size()-1; + dual.vert.back().Q()=i; } + + //then initialize VF first face + for (size_t i=0;i::FaceFace(primal); + vcg::tri::UpdateFlags::VertexBorderFromFaceAdj(primal); std::map, int> VertEdgeMap; - CreateBorderEdgeVert(primal,dual,VertEdgeMap); + std::cout<<"Creating Dual Vertices"< VertFaceMap,VertFace; CreateFaceVert(primal,dual,VertFaceMap,VertFace,snapBorder); + std::cout<<"Creating Dual Faces"< VertSeq; @@ -195,9 +147,11 @@ public: dual.face.back().Alloc(VertSeq.size()); for (size_t j=0;j::RemoveUnreferencedVertex(dual); + //finally remove valence 1 vertices on the border + vcg::PolygonalAlgorithm::RemoveValence2Vertices(dual); } }; diff --git a/vcg/complex/algorithms/parametrization/tangent_field_operators.h b/vcg/complex/algorithms/parametrization/tangent_field_operators.h index 26a997d6..b181211f 100644 --- a/vcg/complex/algorithms/parametrization/tangent_field_operators.h +++ b/vcg/complex/algorithms/parametrization/tangent_field_operators.h @@ -199,7 +199,7 @@ private: //push the first one SubDEdges.push_back(Edge0); - for (size_t i=1;i=0)&&(IndexF0=0)&&(IndexF1=0)&&(IndexF0<(int)OriginalFace.size())); + assert((IndexF1>=0)&&(IndexF1<(int)OriginalFace.size())); FaceType* F0=OriginalFace[IndexF0]; FaceType* F1=OriginalFace[IndexF1]; @@ -394,7 +394,7 @@ private: const TriangleType &t0, const TriangleType &t1, CoordType &Interpolated, - size_t &Face) + int &Face) { //find smallest edge ScalarType smallestE=std::numeric_limits::max(); @@ -511,7 +511,7 @@ private: directions.clear(); faces.clear(); - for (size_t i=0;i=0); - assert(OrigFIndex::Rotate(f0,f1,dirS); ///then get the closest upf to K*PI/2 rotations - CoordType dir1=f1.cPD1(); + //CoordType dir1=f1.cPD1(); //int ret=I_K_PI(dir1,dirR,f1.cN()); CoordType dir[4]; CrossVector(f1,dir); @@ -936,8 +936,8 @@ public: const CoordType &t1=f.V(1)->PD1(); const CoordType &t2=f.V(2)->PD1(); const CoordType &N0=f.V(0)->N(); - const CoordType &N1=f.V(0)->N(); - const CoordType &N2=f.V(0)->N(); + const CoordType &N1=f.V(1)->N(); + const CoordType &N2=f.V(2)->N(); const CoordType &NF=f.N(); const CoordType bary=CoordType(0.33333,0.33333,0.33333); CoordType tF0,tF1; @@ -948,7 +948,9 @@ public: SetCrossVector(f,tF0,tF1); //then set the magnitudo - ScalarType mag1,mag2; + ScalarType mag1=0; + ScalarType mag2=0; + for (int i=0;i<3;i++) { vcg::Matrix33 rotN=vcg::RotationMatrix(f.V(i)->N(),f.N()); diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index 6fcc2416..8c2f8b5b 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -30,6 +30,8 @@ #include #include +#include + //define a temporary triangle mesh type class TempFace; class TempVertex; @@ -169,8 +171,7 @@ private: static bool CollapseBorderSmallEdgesStep(PolyMeshType &poly_m, - const ScalarType edge_limit, - ScalarType angleDeg=100) + const ScalarType edge_limit) { //update topology vcg::tri::UpdateTopology::FaceFace(poly_m); @@ -356,11 +357,19 @@ public: vcg::GetPolyTemplatePos(f,TemplatePos,true); CoordType NormT=Normal(TemplatePos); + //get the normal of vertices - CoordType AVN(0,0,0); + //CoordType AVN(0,0,0); + //CoordType AVN0(0,0,0); CoordType Origin(0,0,0); - for (int j=0;jN(); +// for (int j=0;jN(); + + CoordType AVN=vcg::PolygonNormal(f); + //AVN0.Normalize(); +// std::cout<<"AVN "< avgPos(poly_m.vert.size(),CoordType(0,0,0)); std::vector weightSum(poly_m.vert.size(),0); //then compute the templated positions + for (size_t i=0;i TemplatePos; @@ -416,8 +428,7 @@ public: ScalarType val=vcg::PolyArea(poly_m.face[i]); if (val<(AvgArea*0.00001)) val=(AvgArea*0.00001); - ScalarType W=1.0/val;//poly_m.face[i].Q(); - //ScalarType W=1; + ScalarType W=1.0/val; for (size_t j=0;j1)alpha=1; // if (isnan(alpha))alpha=1; CoordType newP=avgPos[i]/weightSum[i]; + //std::cout<<"W "< SumAngle(poly_m.face.size(),0); -// for (size_t i=0;iQ()+=AreaF * CurrAngle/SumAngle[i]; -// } -// } -// } - static void InitQualityVertVoronoiArea(PolyMeshType &poly_m) { for (size_t i=0;iQ(); (*fi).Q()/=(FaceQualityType)(*fi).VN(); } diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 2d48ed03..a04754c3 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1080,6 +1080,7 @@ public: h._sizeof = sizeof(ATTR_TYPE); h._padding = 0; h._handle = new SimpleTempData(m.vert); + h._type = typeid(ATTR_TYPE); m.attrn++; h.n_attr = m.attrn; std::pair < AttrIterator , bool> res = m.vert_attr.insert(h); @@ -1221,6 +1222,7 @@ public: h._padding = 0; // h._typename = typeid(ATTR_TYPE).name(); h._handle = new SimpleTempData(m.edge); + h._type = typeid(ATTR_TYPE); m.attrn++; h.n_attr = m.attrn; std::pair < AttrIterator , bool> res = m.edge_attr.insert(h); @@ -1344,6 +1346,7 @@ public: h._sizeof = sizeof(ATTR_TYPE); h._padding = 0; h._handle = new SimpleTempData(m.face); + h._type = typeid(ATTR_TYPE); m.attrn++; h.n_attr = m.attrn; std::pair < AttrIterator , bool> res = m.face_attr.insert(h); @@ -1462,6 +1465,7 @@ public: h._sizeof = sizeof(ATTR_TYPE); h._padding = 0; h._handle = new Attribute(); + h._type = typeid(ATTR_TYPE); m.attrn++; h.n_attr = m.attrn; std::pair < AttrIterator , bool> res = m.mesh_attr.insert(h); diff --git a/vcg/complex/base.h b/vcg/complex/base.h index fc178f79..65cfb4a9 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -37,10 +37,12 @@ public: int _padding; // padding (used only with VMI loading) int n_attr; // unique ID of the attribute - + std::type_index _type; void Resize(size_t sz){((SimpleTempDataBase *)_handle)->Resize(sz);} void Reorder(std::vector & newVertIndex){((SimpleTempDataBase *)_handle)->Reorder(newVertIndex);} bool operator<(const PointerToAttribute b) const { return(_name.empty()&&b._name.empty())?(_handle < b._handle):( _name < b._name);} + + PointerToAttribute(): _type(typeid(void)) { }; }; diff --git a/vcg/complex/complex.h b/vcg/complex/complex.h index 0121700e..ebc3dc1e 100644 --- a/vcg/complex/complex.h +++ b/vcg/complex/complex.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index 1389547f..77165733 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -96,7 +96,7 @@ public: } } - typename VALUE_TYPE::ColorType wc[3]; + typename VALUE_TYPE::WedgeColorType wc[3]; }; class WedgeNormalTypePack { @@ -111,7 +111,7 @@ public: } } - typename VALUE_TYPE::NormalType wn[3]; + typename VALUE_TYPE::WedgeNormalType wn[3]; }; diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index e63bd653..dde27016 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -108,6 +108,7 @@ public: T::Dealloc(); } + static bool HasVertexRef() { return true; } static bool HasFVAdjacency() { return true; } static void Name(std::vector & name){name.push_back(std::string("PFVAdj"));T::Name(name);} diff --git a/vcg/space/box3.h b/vcg/space/box3.h index f9e3fccd..69906ce5 100644 --- a/vcg/space/box3.h +++ b/vcg/space/box3.h @@ -323,6 +323,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) template Box3 Point3::GetBBox(Box3 &bb) const { bb.Set( *this ); + return bb; } diff --git a/wrap/gl/gl_field.h b/wrap/gl/gl_field.h index f48f0530..b887801e 100644 --- a/wrap/gl/gl_field.h +++ b/wrap/gl/gl_field.h @@ -74,10 +74,11 @@ public: const ScalarType &size, const bool oneside, const bool onlyPD1, - const ScalarType maxN) + const ScalarType maxN, + const ScalarType minN) { CoordType center=(f.cP(0)+f.cP(1)+f.cP(2))/3; - CoordType normal=f.cN(); + //CoordType normal=f.cN(); CoordType dir[4]; vcg::tri::CrossField::CrossVector(f,dir); @@ -92,10 +93,10 @@ public: ScalarType IntervW=MaxW-MinW; if (Norm0>maxN)Norm0=maxN; if (Norm1>maxN)Norm1=maxN; - vcg::Color4b Col0=vcg::Color4b::ColorRamp(0,maxN,Norm0); - vcg::Color4b Col1=vcg::Color4b::ColorRamp(0,maxN,Norm1); - ScalarType W0=(Norm0/maxN)*IntervW+MinW; - ScalarType W1=(Norm1/maxN)*IntervW+MinW; + vcg::Color4b Col0=vcg::Color4b::ColorRamp(minN,maxN,Norm0); + vcg::Color4b Col1=vcg::Color4b::ColorRamp(minN,maxN,Norm1); + ScalarType W0=(Norm0/(maxN-minN))*IntervW+MinW; + ScalarType W1=(Norm1/(maxN-minN))*IntervW+MinW; GLDrawField(dir,center,size,W0,W1,Col0,Col1,oneside,onlyPD1); } } @@ -132,7 +133,8 @@ public: bool onlyPD1, bool oneside, ScalarType GlobalScale=0.002, - const ScalarType maxN=0) + const ScalarType maxN=0, + const ScalarType minN=0) { glPushAttrib(GL_ALL_ATTRIB_BITS); @@ -144,7 +146,7 @@ public: for (unsigned int i=0;i bset(str); + for (unsigned int ii = 0; ii < ATT_NAMES_DERIVED_CLASS::enumArity(); ++ii) + _atts[ATT_NAMES_DERIVED_CLASS::enumArity() - ii - 1] = bset[ii]; + } + //template //static void computeARequestedAttributesSetCompatibleWithMesh(const MESHTYPE& mesh,const PRIMITIVE_MODALITY_MASK,RenderingAtts& rqatt) //{ @@ -330,6 +344,8 @@ namespace vcg class InternalRendAtts : public RenderingAtts { public: + typedef INT_ATT_NAMES AttName; + InternalRendAtts() :RenderingAtts() { 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 3ead992c..e56470b2 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -118,7 +118,6 @@ namespace vcg return (*this); } - private: void copyData(const RenderingModalityGLOptions& opts) { @@ -156,6 +155,9 @@ namespace vcg class PerViewData : public GLMeshAttributesInfo { public: + + typedef GL_OPTIONS_DERIVED_TYPE GLOptionsType; + PerViewData() :_pmmask(),_intatts(PR_ARITY),_glopts(NULL) { @@ -260,6 +262,53 @@ namespace vcg } } + + void serialize(std::string& str) + { + str.append(_pmmask.to_string()); + for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it) + { + std::string s; + it->serialize(s); + str.append(s); + } + std::string s; + _glopts->serialize(s); + str.append(s); + } + + bool deserialize(const std::string& str) + { + std::string::size_type pos = 0; + std::string token[6]; + token[0] = str.substr(pos, _pmmask.size()); + if (token[0].length() < _pmmask.size()) + return false; + int i = 1; + pos = _pmmask.size(); + for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++) + { + token[i] = str.substr(pos, InternalRendAtts::AttName::enumArity()); + if (token[i].length() < InternalRendAtts::AttName::enumArity()) + return false; + pos = pos + InternalRendAtts::AttName::enumArity(); + } + if (_glopts != NULL) + { + int size = _glopts->serialize(std::string()); + token[i] = str.substr(pos, size); + if (token[i].length() < size) + return false; + } + _pmmask = PRIMITIVE_MODALITY_MASK(token[0]); + i = 1; + for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++) + it->deserialize(token[i]); + if (_glopts != NULL) + _glopts->deserialize(token[i]); + return true; + } + protected: template friend class NotThreadSafeGLMeshAttributesMultiViewerBOManager; diff --git a/wrap/igl/miq_parametrization.h b/wrap/igl/miq_parametrization.h index 51a531a5..6ed928fa 100644 --- a/wrap/igl/miq_parametrization.h +++ b/wrap/igl/miq_parametrization.h @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include @@ -74,6 +74,8 @@ public: bool crease_as_feature; //true if roound selected vert bool round_selected; + //the anisotropy in MIQ sense (see paper) + double miqAnisotropy; MIQParameters() { @@ -89,6 +91,7 @@ public: Ndir=4; crease_thr=0.2; hexaLine=false; + miqAnisotropy=1; } }; @@ -163,9 +166,9 @@ private: } } - igl::miq(V,F,X1,X2,UV,FUV,MiqP.gradient,MiqP.stiffness,MiqP.directRound, + igl::copyleft::comiso::miq(V,F,X1,X2,UV,FUV,MiqP.gradient,MiqP.stiffness,MiqP.directRound, MiqP.stiffness_iter,MiqP.local_iter,MiqP.doRound,MiqP.round_singularities, - extra_round,hard_features); + extra_round,hard_features,MiqP.miqAnisotropy); // then copy UV for (size_t i=0;i0)|| - (SParam.sharp_thr>0)|| - (SParam.curv_thr>0)) - InitByCurvature(mesh,SParam.curvRing); +// if ((SParam.alpha_curv>0)|| +// (SParam.sharp_thr>0)|| +// (SParam.curv_thr>0)) + InitByCurvature(mesh,SParam.curvRing); SelectConstraints(mesh,SParam); //then do the actual smooth diff --git a/wrap/io_trimesh/import_field.h b/wrap/io_trimesh/import_field.h index 2ba37c58..d7c5ad23 100644 --- a/wrap/io_trimesh/import_field.h +++ b/wrap/io_trimesh/import_field.h @@ -109,33 +109,33 @@ public: printf("%d\n",period); fscanf(f,"%c",&final); fseek(f, -1, SEEK_CUR); - printf("%s\n",&final[0]); + //printf("%s\n",&final[0]); }while(strcmp(final,"\"")!=0); // printf("%s\n",skipstr); fflush(stdout); - // for (int i=0;i UV[3]; - // UV[0]= vcg::Point2(u0,v0); - // UV[1]= vcg::Point2(u1,v1); - // UV[2]= vcg::Point2(u2,v2); - // CoordType dir1; - // CoordType dir2; - // vcg::tri::CrossField::GradientToCross(mesh.face[i],UV[0],UV[1],UV[2],dir1,dir2); - // dir1.Normalize(); - // dir2.Normalize(); - // mesh.face[i].PD1()=dir1; - // mesh.face[i].PD2()=dir2; - // } - // fclose(f); - // return true; + for (int i=0;i UV[3]; + UV[0]= vcg::Point2(u0,v0); + UV[1]= vcg::Point2(u1,v1); + UV[2]= vcg::Point2(u2,v2); + CoordType dir1; + CoordType dir2; + vcg::tri::CrossField::GradientToCross(mesh.face[i],UV[0],UV[1],UV[2],dir1,dir2); + dir1.Normalize(); + dir2.Normalize(); + mesh.face[i].PD1()=dir1; + mesh.face[i].PD2()=dir2; + } + fclose(f); + return true; } ///load a field on the mesh, it could be a vfield file (per vertex) diff --git a/wrap/io_trimesh/import_ply.h b/wrap/io_trimesh/import_ply.h index 52f4463a..a37e9240 100644 --- a/wrap/io_trimesh/import_ply.h +++ b/wrap/io_trimesh/import_ply.h @@ -115,7 +115,7 @@ struct LoadPly_VertAux S p[3]; S n[3]; int flags; - float q; // the confidence + S q; // the confidence float intensity; unsigned char r; unsigned char g; @@ -189,7 +189,7 @@ static const PropDescriptor &VertDesc(int i) /*27*/ {"vertex", "nx", ply::T_DOUBLE, PlyType(),offsetof(LoadPly_VertAux,n) ,0,0,0,0,0 ,0}, /*28*/ {"vertex", "ny", ply::T_DOUBLE, PlyType(),offsetof(LoadPly_VertAux,n) + 1*sizeof(ScalarType),0,0,0,0,0 ,0}, /*29*/ {"vertex", "nz", ply::T_DOUBLE, PlyType(),offsetof(LoadPly_VertAux,n) + 2*sizeof(ScalarType),0,0,0,0,0 ,0}, -/*30*/ {"vertex", "radius", ply::T_DOUBLE, ply::T_FLOAT, offsetof(LoadPly_VertAux,radius),0,0,0,0,0 ,0}, +/*30*/ {"vertex", "radius", ply::T_DOUBLE, PlyType(),offsetof(LoadPly_VertAux,radius),0,0,0,0,0 ,0}, /*31*/ {"vertex", "quality", ply::T_DOUBLE, PlyType(),offsetof(LoadPly_VertAux,q),0,0,0,0,0 ,0} }; return pv[i]; diff --git a/wrap/nanoply/include/nanoply.hpp b/wrap/nanoply/include/nanoply.hpp index 071f5365..3f867c41 100644 --- a/wrap/nanoply/include/nanoply.hpp +++ b/wrap/nanoply/include/nanoply.hpp @@ -246,7 +246,7 @@ namespace nanoply { PlyEntity::NNP_K2DIR, NameVector({ "k2dir" }) }, { PlyEntity::NNP_EDGE_V1, NameVector({ "vertex1", "v1" }) }, { PlyEntity::NNP_EDGE_V2, NameVector({ "vertex2", "v2" }) }, - { PlyEntity::NNP_FACE_VERTEX_LIST, NameVector({ "vertex_index", "vertex_indices" }) }, + { PlyEntity::NNP_FACE_VERTEX_LIST, NameVector({ "vertex_indices", "vertex_index" }) }, { PlyEntity::NNP_FACE_WEDGE_COLOR, NameVector({ "color" }) }, { PlyEntity::NNP_FACE_WEDGE_NORMAL, NameVector({ "normal" }) }, { PlyEntity::NNP_FACE_WEDGE_TEX, NameVector({ "texcoord" }) } @@ -463,7 +463,7 @@ namespace nanoply if (fileStream.fail()) return false; bufferOffset = 0; - //fileStream.setf(std::ios::fixed, std::ios::floatfield); + fileStream.setf(std::ios::fixed, std::ios::floatfield); //fileStream.precision(7); return true; } @@ -476,7 +476,7 @@ namespace nanoply std::getline(fileStream, line); std::transform(line.begin(), line.end(), line.begin(), ::tolower); last = false; - if (line == "end_header") + if (line.find("end_header") != std::string::npos) last = true; return true; } @@ -583,6 +583,10 @@ namespace nanoply PlyEntity elem; /**< Property entity. */ bool validToWrite; /**< Property validity (necessary to write the header). */ + + inline PlyProperty() {} + + /** * Constructor that sets the type and the entity of a standard PLY property. * @@ -1139,7 +1143,7 @@ namespace nanoply token = strtok(tempStr, " \t"); if (strstr(token, "element") == NULL) return false; - token = strtok(0, " \t\n"); + token = strtok(0, " \t\r\n"); name = std::string(token); plyElem = PlyElemEntity::NNP_UNKNOWN_ELEM; ElementMapIterator iter = mapElem.begin(); @@ -1162,7 +1166,7 @@ namespace nanoply } iter++; } - token = strtok(0, " \t\n"); + token = strtok(0, " \t\r\n"); cnt = atoi(token); for (size_t i = 0; i < propStr.size(); i++) if (!AddProperty(propStr[i])) @@ -1512,7 +1516,7 @@ namespace nanoply { this->filename = filename; this->errInfo = NNP_OK; - std::ifstream input(filename, std::ios::binary); + std::ifstream input(filename); if (!input.good()) { this->errInfo = NNP_UNABLE_TO_OPEN; @@ -1732,7 +1736,7 @@ namespace nanoply * @param _s Name of the PlyProperty. * @param _b Pointer to the memory location that contains the data of the property. */ - inline DescriptorInterface(std::string& _s, void *_b) :curPos(0), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_s), base(_b){}; + inline DescriptorInterface(const std::string& _s, void *_b) :curPos(0), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_s), base(_b){}; /** * Restart the descriptor. @@ -1990,18 +1994,336 @@ namespace nanoply + template + class DescriptorHelper + { + + public: + + template + static void ReadBinary(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop, bool fixEndian) + { + char * buffer = nullptr; + int size; + int count = prop.CountValue(); + int typeSize = prop.TypeSize(); + if (prop.type >= NNP_LIST_UINT8_UINT32) + { + file.ReadBinaryData(buffer, sizeof(char)); + const int cntList = int(*(reinterpret_cast(buffer))); + size = typeSize * cntList; + count = cntList; + } + else + size = typeSize * count; + file.ReadBinaryData(buffer, size); + + if (typeSize > 1 && fixEndian) + adjustEndianess(reinterpret_cast(buffer), typeSize, count); + + unsigned char* baseProp = (unsigned char*)descr.base + descr.curPos * sizeof(ContainerType); + C* temp = (C*)buffer; + if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) + { + float norm = 1.0f; + if (std::is_same::value && std::is_same::value) + norm = 1.0f / 255.0f; + else if (std::is_same::value && std::is_same::value) + norm = 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i * sizeof(ScalarType))) = ScalarType(temp[i] * norm); + } + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i * sizeof(ScalarType))) = ScalarType(temp[i]); + } + ++(descr.curPos); + } + + template + static void ReadAscii(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop) + { + int count = prop.CountValue(); + if (prop.type >= NNP_LIST_UINT8_UINT32) + file.ReadAsciiData(count); + + C* temp = new C[count]; + for (int i = 0; i < count; i++) + file.ReadAsciiData(temp[i]); + + unsigned char* baseProp = (unsigned char*)descr.base + descr.curPos * sizeof(ContainerType); + if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) + { + float norm = 1.0f; + if (std::is_same::value && prop.type == NNP_UINT8) + norm = 1.0f / 255.0f; + else if (std::is_same::value && prop.type == NNP_FLOAT32) + norm = 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i * sizeof(ScalarType))) = ScalarType(temp[i] * norm); + } + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i * sizeof(ScalarType))) = ScalarType(temp[i]); + } + delete[] temp; + ++(descr.curPos); + } + + template + static void WriteBinary(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop, bool fixEndian) + { + (void)fixEndian; + int count = prop.CountValue(); + C data[VectorSize]; + if (prop.type >= NNP_LIST_UINT8_UINT32) + { + if (prop.IsSigned()) + { + char listSize = (char)VectorSize; + file.WriteBinaryData(&listSize, 1); + count = VectorSize; + } + else + { + unsigned char listSize = (unsigned char)VectorSize; + file.WriteBinaryData(&listSize, 1); + count = VectorSize; + } + } + + C temp = 0; + unsigned char* baseProp = (unsigned char*)descr.base + descr.curPos * sizeof(ContainerType); + if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) + { + float norm = 1.0f; + if (std::is_same::value && std::is_same::value) + norm = 255.0f; + else if (std::is_same::value && std::is_same::value) + norm = 1.0f / 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i * sizeof(ScalarType))) * norm); + } + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i * sizeof(ScalarType)))); + } + + if (sizeof(C) > 1 && fixEndian) + adjustEndianess((unsigned char*)data, sizeof(C), std::min(VectorSize, count)); + + file.WriteBinaryData(data, sizeof(C)*std::min(VectorSize, count)); + for (int i = 0; i < (count - VectorSize); i++) + file.WriteBinaryData(&temp, sizeof(C)); + ++(descr.curPos); + } + + template + static void WriteAscii(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop) + { + int count = prop.CountValue(); + if (prop.type >= NNP_LIST_UINT8_UINT32) + { + if (prop.IsSigned()) + { + int listSize = (int)VectorSize; + file.WriteAsciiData(listSize); + count = VectorSize; + } + else + { + unsigned int listSize = (unsigned int)VectorSize; + file.WriteAsciiData(listSize); + count = VectorSize; + } + file.WriteAsciiData(std::string(" ")); + } + + C data[VectorSize]; + unsigned char* baseProp = (unsigned char*)descr.base + descr.curPos * sizeof(ContainerType); + if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) + { + float norm = 1.0; + if (std::is_same::value && prop.type == NNP_UINT8) + norm = 255.0f; + else if (std::is_same::value && prop.type == NNP_FLOAT32) + norm = 1.0f / 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i * sizeof(ScalarType))) * norm); + } + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i * sizeof(ScalarType)))); + } + + + for (int i = 0; i < (count - VectorSize); i++) + data[i] = 0; + + for (int i = 0; i < count; i++) + { + file.WriteAsciiData(data[i]); + if (i < count - 1) + file.WriteAsciiData(std::string(" ")); + } + ++(descr.curPos); + } + }; + + + + + template + class DescriptorHelper + { + + public: + + template + static void ReadBinary(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop, bool fixEndian) + { + char * buffer = nullptr; + int size; + int count = prop.CountValue(); + int typeSize = prop.TypeSize(); + if (prop.type >= NNP_LIST_UINT8_UINT32) + { + file.ReadBinaryData(buffer, sizeof(char)); + const int cntList = int(*(reinterpret_cast(buffer))); + size = typeSize * cntList; + count = cntList; + } + else + size = typeSize * count; + file.ReadBinaryData(buffer, size); + + if (typeSize > 1 && fixEndian) + adjustEndianess(reinterpret_cast(buffer), typeSize, count); + + C* temp = (C*)buffer; + + ContainerType* container = (ContainerType*)((unsigned char*)descr.base + descr.curPos * sizeof(ContainerType)); + (*container).resize(count); + for (int i = 0; i < count; i++) + (*container)[i] = (ScalarType)(temp[i]); + ++(descr.curPos); + } + + template + static void ReadAscii(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop) + { + int count = prop.CountValue(); + if (prop.type >= NNP_LIST_UINT8_UINT32) + file.ReadAsciiData(count); + + C* temp = new C[count]; + for (int i = 0; i < count; i++) + file.ReadAsciiData(temp[i]); + + ContainerType* container = (ContainerType*)((unsigned char*)descr.base + descr.curPos * sizeof(ContainerType)); + (*container).resize(count); + for (int i = 0; i < count; i++) + (*container)[i] = (ScalarType)(temp[i]); + delete[] temp; + ++(descr.curPos); + } + + template + static void WriteBinary(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop, bool fixEndian) + { + size_t count = prop.CountValue(); + ContainerType* list = (ContainerType*)((unsigned char*)descr.base + descr.curPos * sizeof(ContainerType)); + if (prop.type >= NNP_LIST_UINT8_UINT32) + { + if (prop.IsSigned()) + { + char listSize = (char)list->size(); + file.WriteBinaryData(&listSize, 1); + count = list->size(); + } + else + { + unsigned char listSize = (unsigned char)list->size(); + file.WriteBinaryData(&listSize, 1); + count = list->size(); + } + } + + std::vector data(count); + + for (int i = 0; i < std::min(count, list->size()); i++) + data[i] = (C)((*list)[i]); + + if (sizeof(C) > 1 && fixEndian) + adjustEndianess((unsigned char*)data.data(), sizeof(C), std::min(count, list->size())); + + file.WriteBinaryData(data.data(), sizeof(C)*std::min(count, list->size())); + C temp = 0; + for (int i = 0; i < (count - list->size()); i++) + file.WriteBinaryData(&temp, sizeof(C)); + ++(descr.curPos); + } + + template + static void WriteAscii(DescriptorInterface& descr, PlyFile &file, PlyProperty &prop) + { + size_t count = prop.CountValue(); + ContainerType* list = (ContainerType*)((unsigned char*)descr.base + descr.curPos * sizeof(ContainerType)); + if (prop.type >= NNP_LIST_UINT8_UINT32) + { + if (prop.IsSigned()) + { + int listSize = (int)list->size(); + file.WriteAsciiData(listSize); + count = list->size(); + } + else + { + unsigned int listSize = (unsigned int)list->size(); + file.WriteAsciiData(listSize); + count = list->size(); + } + file.WriteAsciiData(std::string(" ")); + } + + std::vector data(count); + for (int i = 0; i < std::min(count, list->size()); i++) + data[i] = (C)((*list)[i]); + + for (int i = 0; i < (count - list->size()); i++) + data[i] = 0; + + for (int i = 0; i < count; i++) + { + file.WriteAsciiData(data[i]); + if (i < count - 1) + file.WriteAsciiData(std::string(" ")); + } + ++(descr.curPos); + } + }; + + + + /** Memory descriptor of a vector of properties. * The class defines how a vector of PlyProperty is saved in memory. * - * @tparam CointainerType Type of the container of the property + * @tparam ContainerType Type of the container of the property * @tparam VectorSize Number of values stored in the property. * @tparam ScalarType Type of the values stored in the property. */ - template + template class DataDescriptor : public DescriptorInterface { public: + DescriptorHelper helper; + inline DataDescriptor(); /** @@ -2018,7 +2340,7 @@ namespace nanoply * @param _s Name of the PlyProperty. * @param _b Pointer to the memory location that contains the data of the property. */ - inline DataDescriptor(std::string& _s, void *_b) :DescriptorInterface(_s, _b){}; + inline DataDescriptor(const std::string& _s, void *_b) :DescriptorInterface(_s, _b){}; inline void Restart(); @@ -2029,75 +2351,18 @@ namespace nanoply inline bool WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); inline bool WriteElemAscii(PlyFile &file, PlyProperty &prop); - - private: - - template - inline void ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); - - template - inline void ReadAscii(PlyFile &file, PlyProperty &prop); - - template - inline void WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); - - template - inline void WriteAscii(PlyFile &file, PlyProperty &prop); - }; + - - template - inline void DataDescriptor::Restart() + template + void DataDescriptor::Restart() { this->curPos = 0; } + template - template - inline void DataDescriptor::ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) - { - char * buffer = nullptr; - int size; - int count = prop.CountValue(); - int typeSize = prop.TypeSize(); - if (prop.type >= NNP_LIST_UINT8_UINT32) - { - file.ReadBinaryData(buffer, sizeof(char)); - const int cntList = int(*(reinterpret_cast(buffer))); - size = typeSize * cntList; - count = cntList; - } - else - size = typeSize * count; - file.ReadBinaryData(buffer, size); - - if (typeSize > 1 && fixEndian) - adjustEndianess(reinterpret_cast(buffer), typeSize, count); - - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - C* temp = (C*)buffer; - if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) - { - float norm = 1.0f; - if (std::is_same::value && std::is_same::value) - norm = 1.0f / 255.0f; - else if (std::is_same::value && std::is_same::value) - norm = 255.0f; - for (int i = 0; i < std::min(VectorSize, count); i++) - *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); - } - else - { - for (int i = 0; i < std::min(VectorSize, count); i++) - *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i]); - } - ++(this->curPos); - } - - - template - inline bool DataDescriptor::ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) + bool DataDescriptor::ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) { if (prop.elem != elem) return false; @@ -2105,70 +2370,35 @@ namespace nanoply { case NNP_LIST_INT8_INT8: case NNP_LIST_UINT8_INT8: - case NNP_INT8: this->ReadBinary(file, prop, fixEndian); break; + case NNP_INT8: helper.ReadBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_UINT8: case NNP_LIST_UINT8_UINT8: - case NNP_UINT8: this->ReadBinary(file, prop, fixEndian); break; + case NNP_UINT8: helper.ReadBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_INT16: case NNP_LIST_UINT8_INT16: - case NNP_INT16: this->ReadBinary(file, prop, fixEndian); break; + case NNP_INT16: helper.ReadBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_UINT16: case NNP_LIST_UINT8_UINT16: - case NNP_UINT16: this->ReadBinary(file, prop, fixEndian); break; + case NNP_UINT16: helper.ReadBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_FLOAT32: case NNP_LIST_UINT8_FLOAT32: - case NNP_FLOAT32: this->ReadBinary(file, prop, fixEndian); break; + case NNP_FLOAT32: helper.ReadBinary(*this, file, prop, fixEndian); break; case NNP_LIST_UINT8_INT32: case NNP_LIST_INT8_INT32: - case NNP_INT32: this->ReadBinary(file, prop, fixEndian); break; + case NNP_INT32: helper.ReadBinary(*this, file, prop, fixEndian); break; case NNP_LIST_UINT8_UINT32: case NNP_LIST_INT8_UINT32: - case NNP_UINT32: this->ReadBinary(file, prop, fixEndian); break; + case NNP_UINT32: helper.ReadBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_FLOAT64: case NNP_LIST_UINT8_FLOAT64: - case NNP_FLOAT64: this->ReadBinary(file, prop, fixEndian); break; + case NNP_FLOAT64: helper.ReadBinary(*this, file, prop, fixEndian); break; } return true; } - template - template - inline void DataDescriptor::ReadAscii(PlyFile &file, PlyProperty &prop) - { - int count = prop.CountValue(); - if (prop.type >= NNP_LIST_UINT8_UINT32) - file.ReadAsciiData(count); - - C* temp = new C[count]; - for (int i = 0; i < count; i++) - file.ReadAsciiData(temp[i]); - - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) - { - float norm = 1.0f; - if (std::is_same::value && prop.type == NNP_UINT8) - norm = 1.0f / 255.0f; - else if (std::is_same::value && prop.type == NNP_FLOAT32) - norm = 255.0f; - for (int i = 0; i < std::min(VectorSize, count); i++) - *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); - } - else - { - for (int i = 0; i < std::min(VectorSize, count); i++) - *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i]); - } - delete[] temp; - ++(this->curPos); - } - - - - template - inline bool DataDescriptor::ReadElemAscii(PlyFile &file, PlyProperty &prop) + bool DataDescriptor::ReadElemAscii(PlyFile &file, PlyProperty &prop) { if (prop.elem != elem) return false; @@ -2176,87 +2406,35 @@ namespace nanoply { case NNP_LIST_UINT8_INT8: case NNP_LIST_INT8_INT8: - case NNP_INT8: this->ReadAscii(file, prop); break; + case NNP_INT8: helper.ReadAscii(*this, file, prop); break; case NNP_LIST_UINT8_UINT8: case NNP_LIST_INT8_UINT8: - case NNP_UINT8: this->ReadAscii(file, prop); break; + case NNP_UINT8: helper.ReadAscii(*this, file, prop); break; case NNP_LIST_UINT8_INT16: case NNP_LIST_INT8_INT16: - case NNP_INT16: this->ReadAscii(file, prop); break; + case NNP_INT16: helper.ReadAscii(*this, file, prop); break; case NNP_LIST_UINT8_UINT16: case NNP_LIST_INT8_UINT16: - case NNP_UINT16: this->ReadAscii(file, prop); break; + case NNP_UINT16: helper.ReadAscii(*this, file, prop); break; case NNP_LIST_UINT8_FLOAT32: case NNP_LIST_INT8_FLOAT32: - case NNP_FLOAT32: this->ReadAscii(file, prop); break; + case NNP_FLOAT32: helper.ReadAscii(*this, file, prop); break; case NNP_LIST_UINT8_INT32: case NNP_LIST_INT8_INT32: - case NNP_INT32: this->ReadAscii(file, prop); break; + case NNP_INT32: helper.ReadAscii(*this, file, prop); break; case NNP_LIST_UINT8_UINT32: case NNP_LIST_INT8_UINT32: - case NNP_UINT32: this->ReadAscii(file, prop); break; + case NNP_UINT32: helper.ReadAscii(*this, file, prop); break; case NNP_LIST_UINT8_FLOAT64: case NNP_LIST_INT8_FLOAT64: - case NNP_FLOAT64: this->ReadAscii(file, prop); break; + case NNP_FLOAT64: helper.ReadAscii(*this, file, prop); break; } return true; } - template - template - inline void DataDescriptor::WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) - { - (void)fixEndian; - int count = prop.CountValue(); - C data[VectorSize]; - if (prop.type >= NNP_LIST_UINT8_UINT32) - { - if (prop.IsSigned()) - { - char listSize = (char)VectorSize; - file.WriteBinaryData(&listSize, 1); - count = VectorSize; - } - else - { - unsigned char listSize = (unsigned char)VectorSize; - file.WriteBinaryData(&listSize, 1); - count = VectorSize; - } - } - - C temp = 0; - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) - { - float norm = 1.0f; - if (std::is_same::value && std::is_same::value) - norm = 255.0f; - else if (std::is_same::value && std::is_same::value) - norm = 1.0f / 255.0f; - for (int i = 0; i < std::min(VectorSize, count); i++) - data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm); - } - else - { - for (int i = 0; i < std::min(VectorSize, count); i++) - data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType)))); - } - - if (sizeof(C) > 1 && fixEndian) - adjustEndianess((unsigned char*)data, sizeof(C), std::min(VectorSize, count)); - - file.WriteBinaryData(data, sizeof(C)*std::min(VectorSize, count)); - for (int i = 0; i < (count - VectorSize); i++) - file.WriteBinaryData(&temp, sizeof(C)); - ++(this->curPos); - } - - - template - inline bool DataDescriptor::WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) + bool DataDescriptor::WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) { if (prop.elem != elem) return false; @@ -2264,89 +2442,35 @@ namespace nanoply { case NNP_LIST_INT8_INT8: case NNP_LIST_UINT8_INT8: - case NNP_INT8: this->WriteBinary(file, prop, fixEndian); break; + case NNP_INT8: helper.WriteBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_UINT8: case NNP_LIST_UINT8_UINT8: - case NNP_UINT8: this->WriteBinary(file, prop, fixEndian); break; + case NNP_UINT8: helper.WriteBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_INT16: case NNP_LIST_UINT8_INT16: - case NNP_INT16: this->WriteBinary(file, prop, fixEndian); break; + case NNP_INT16: helper.WriteBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_UINT16: case NNP_LIST_UINT8_UINT16: - case NNP_UINT16: this->WriteBinary(file, prop, fixEndian); break; + case NNP_UINT16: helper.WriteBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_FLOAT32: case NNP_LIST_UINT8_FLOAT32: - case NNP_FLOAT32: this->WriteBinary(file, prop, fixEndian); break; + case NNP_FLOAT32: helper.WriteBinary(*this, file, prop, fixEndian); break; case NNP_LIST_UINT8_INT32: case NNP_LIST_INT8_INT32: - case NNP_INT32: this->WriteBinary(file, prop, fixEndian); break; + case NNP_INT32: helper.WriteBinary(*this, file, prop, fixEndian); break; case NNP_LIST_UINT8_UINT32: case NNP_LIST_INT8_UINT32: - case NNP_UINT32: this->WriteBinary(file, prop, fixEndian); break; + case NNP_UINT32: helper.WriteBinary(*this, file, prop, fixEndian); break; case NNP_LIST_INT8_FLOAT64: case NNP_LIST_UINT8_FLOAT64: - case NNP_FLOAT64: this->WriteBinary(file, prop, fixEndian); break; + case NNP_FLOAT64: helper.WriteBinary(*this, file, prop, fixEndian); break; } return true; } template - template - inline void DataDescriptor::WriteAscii(PlyFile &file, PlyProperty &prop) - { - int count = prop.CountValue(); - if (prop.type >= NNP_LIST_UINT8_UINT32) - { - if (prop.IsSigned()) - { - int listSize = (int)VectorSize; - file.WriteAsciiData(listSize); - count = VectorSize; - } - else - { - unsigned int listSize = (unsigned int)VectorSize; - file.WriteAsciiData(listSize); - count = VectorSize; - } - file.WriteAsciiData(std::string(" ")); - } - - C data[VectorSize]; - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) - { - float norm = 1.0; - if (std::is_same::value && prop.type == NNP_UINT8) - norm = 255.0f; - else if (std::is_same::value && prop.type == NNP_FLOAT32) - norm = 1.0f / 255.0f; - for (int i = 0; i < std::min(VectorSize, count); i++) - data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm); - } - else - { - for (int i = 0; i < std::min(VectorSize, count); i++) - data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType)))); - } - - - for (int i = 0; i < (count - VectorSize); i++) - data[i] = 0; - - for (int i = 0; i < count; i++) - { - file.WriteAsciiData(data[i]); - if (i < count - 1) - file.WriteAsciiData(std::string(" ")); - } - ++(this->curPos); - } - - - template - inline bool DataDescriptor::WriteElemAscii(PlyFile &file, PlyProperty& prop) + bool DataDescriptor::WriteElemAscii(PlyFile &file, PlyProperty& prop) { if (prop.elem != elem) return false; @@ -2356,28 +2480,28 @@ namespace nanoply { case NNP_LIST_UINT8_INT8: case NNP_LIST_INT8_INT8: - case NNP_INT8: this->WriteAscii(file, prop); break; + case NNP_INT8: helper.WriteAscii(*this, file, prop); break; case NNP_LIST_UINT8_UINT8: case NNP_LIST_INT8_UINT8: - case NNP_UINT8: this->WriteAscii(file, prop); break; + case NNP_UINT8: helper.WriteAscii(*this, file, prop); break; case NNP_LIST_UINT8_INT16: case NNP_LIST_INT8_INT16: - case NNP_INT16: this->WriteAscii(file, prop); break; + case NNP_INT16: helper.WriteAscii(*this, file, prop); break; case NNP_LIST_UINT8_UINT16: case NNP_LIST_INT8_UINT16: - case NNP_UINT16: this->WriteAscii(file, prop); break; + case NNP_UINT16: helper.WriteAscii(*this, file, prop); break; case NNP_LIST_UINT8_FLOAT32: case NNP_LIST_INT8_FLOAT32: - case NNP_FLOAT32: this->WriteAscii(file, prop); break; + case NNP_FLOAT32: helper.WriteAscii(*this, file, prop); break; case NNP_LIST_UINT8_INT32: case NNP_LIST_INT8_INT32: - case NNP_INT32: this->WriteAscii(file, prop); break; + case NNP_INT32: helper.WriteAscii(*this, file, prop); break; case NNP_LIST_UINT8_UINT32: case NNP_LIST_INT8_UINT32: - case NNP_UINT32: this->WriteAscii(file, prop); break; + case NNP_UINT32: helper.WriteAscii(*this, file, prop); break; case NNP_LIST_UINT8_FLOAT64: case NNP_LIST_INT8_FLOAT64: - case NNP_FLOAT64: this->WriteAscii(file, prop); break; + case NNP_FLOAT64: helper.WriteAscii(*this, file, prop); break; } return true; } diff --git a/wrap/nanoply/include/nanoplyWrapper.hpp b/wrap/nanoply/include/nanoplyWrapper.hpp index 6fd77eab..c5f3a87c 100644 --- a/wrap/nanoply/include/nanoplyWrapper.hpp +++ b/wrap/nanoply/include/nanoplyWrapper.hpp @@ -19,6 +19,8 @@ #include #include +#include + namespace nanoply { @@ -28,38 +30,49 @@ namespace nanoply private: - typedef typename MeshType::PointerToAttribute PointerToAttribute; - typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::PointerToAttribute PointerToAttribute; + typedef typename MeshType::ScalarType ScalarType; - typedef typename MeshType::VertexType VertexType; - typedef typename MeshType::VertexType::ScalarType VertexCoordScalar; - typedef typename MeshType::VertexType::NormalType::ScalarType VertexNormScalar; - typedef typename MeshType::VertexType::ColorType::ScalarType VertexColorScalar; - typedef typename MeshType::VertexType::QualityType VertexQuality; - typedef typename MeshType::VertexType::RadiusType VertexRadius; - typedef typename MeshType::VertexType::FlagType VertexFlag; - typedef typename MeshType::VertexType::TexCoordType::ScalarType VertexTexScalar; - typedef typename MeshType::VertexType::CurvatureType::ScalarType VertexCurScalar; - typedef typename MeshType::VertexType::CurScalarType VertexDirCurScalar; - typedef typename MeshType::VertexType::CurVecType::ScalarType VertexDirCurVecScalar; + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::VertexType::ScalarType VertexCoordScalar; + typedef typename MeshType::VertexType::NormalType VertexNormalType; + typedef typename MeshType::VertexType::NormalType::ScalarType VertexNormScalar; + typedef typename MeshType::VertexType::ColorType VertexColorType; + typedef typename MeshType::VertexType::ColorType::ScalarType VertexColorScalar; + typedef typename MeshType::VertexType::QualityType VertexQuality; + typedef typename MeshType::VertexType::RadiusType VertexRadius; + typedef typename MeshType::VertexType::FlagType VertexFlag; + typedef typename MeshType::VertexType::TexCoordType VertexTexCoordType; + typedef typename MeshType::VertexType::TexCoordType::ScalarType VertexTexScalar; + typedef typename MeshType::VertexType::CurvatureType VertexCurType; + typedef typename MeshType::VertexType::CurvatureType::ScalarType VertexCurScalar; + typedef typename MeshType::VertexType::CurvatureDirType VertexCurDirType; + typedef typename MeshType::VertexType::CurScalarType VertexDirCurScalar; + typedef typename MeshType::VertexType::CurVecType::ScalarType VertexDirCurVecScalar; - typedef typename MeshType::EdgeType EdgeType; - typedef typename MeshType::EdgeType::ColorType::ScalarType EdgeColorScalar; - typedef typename MeshType::EdgeType::QualityType EdgeQuality; - typedef typename MeshType::EdgeType::FlagType EdgeFlag; + typedef typename MeshType::EdgeType EdgeType; + typedef typename MeshType::EdgeType::ColorType::ScalarType EdgeColorScalar; + typedef typename MeshType::EdgeType::QualityType EdgeQuality; + typedef typename MeshType::EdgeType::FlagType EdgeFlag; - typedef typename MeshType::FaceType FaceType; - typedef typename MeshType::FaceType::NormalType::ScalarType FaceNormScalar; - typedef typename MeshType::FaceType::ColorType::ScalarType FaceColorScalar; - typedef typename MeshType::FaceType::QualityType FaceQuality; - typedef typename MeshType::FaceType::FlagType FaceFlag; - typedef typename MeshType::FaceType::TexCoordType::ScalarType FaceTexScalar; - typedef typename MeshType::FaceType::CurScalarType FaceDirCurScalar; - typedef typename MeshType::FaceType::CurVecType::ScalarType FaceDirCurVecScalar; - typedef typename MeshType::FaceType::WedgeColorType::ScalarType WedgeColorScalar; - typedef typename MeshType::FaceType::WedgeNormalType::ScalarType WedgeNormalScalar; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FaceType::NormalType FaceNormalType; + typedef typename MeshType::FaceType::NormalType::ScalarType FaceNormScalar; + typedef typename MeshType::FaceType::ColorType FaceColorType; + typedef typename MeshType::FaceType::ColorType::ScalarType FaceColorScalar; + typedef typename MeshType::FaceType::QualityType FaceQuality; + typedef typename MeshType::FaceType::FlagType FaceFlag; + typedef typename vcg::face::vector_ocf::WedgeTexTypePack FaceTexCoordType; + typedef typename MeshType::FaceType::TexCoordType::ScalarType FaceTexScalar; + typedef typename MeshType::FaceType::CurvatureDirType FaceCurDirType; + typedef typename MeshType::FaceType::CurScalarType FaceDirCurScalar; + typedef typename MeshType::FaceType::CurVecType::ScalarType FaceDirCurVecScalar; + typedef typename vcg::face::vector_ocf::WedgeColorTypePack WedgeColorType; + typedef typename MeshType::FaceType::WedgeColorType::ScalarType WedgeColorScalar; + typedef typename vcg::face::vector_ocf::WedgeNormalTypePack WedgeNormalType; + typedef typename MeshType::FaceType::WedgeNormalType::ScalarType WedgeNormalScalar; - + typedef typename MeshType::FaceIterator FaceIterator; template static PlyType getEntity() { return NNP_UNKNOWN_TYPE }; template<> static PlyType getEntity(){ return NNP_UINT8; }; @@ -120,38 +133,40 @@ namespace nanoply public: - typedef enum { - IO_NONE = 0x00000000, + typedef enum { + IO_NONE = 0x00000000, - IO_VERTCOORD = 0x00000001, - IO_VERTFLAGS = 0x00000002, - IO_VERTCOLOR = 0x00000004, - IO_VERTQUALITY = 0x00000008, - IO_VERTNORMAL = 0x00000010, - IO_VERTTEXCOORD = 0x00000020, - IO_VERTRADIUS = 0x00000040, - IO_VERTCURV = 0x00000080, - IO_VERTCURVDIR = 0x00000100, - IO_VERTATTRIB = 0x00000200, + IO_VERTCOORD = 0x00000001, + IO_VERTFLAGS = 0x00000002, + IO_VERTCOLOR = 0x00000004, + IO_VERTQUALITY = 0x00000008, + IO_VERTNORMAL = 0x00000010, + IO_VERTTEXCOORD = 0x00000020, + IO_VERTRADIUS = 0x00000040, + IO_VERTCURV = 0x00000080, + IO_VERTCURVDIR = 0x00000100, + IO_VERTATTRIB = 0x00000200, - IO_FACEINDEX = 0x00000400, - IO_FACEFLAGS = 0x00000800, - IO_FACECOLOR = 0x00001000, - IO_FACEQUALITY = 0x00002000, - IO_FACENORMAL = 0x00004000, - IO_FACECURVDIR = 0x00008000, - IO_FACEATTRIB = 0x00010000, + IO_FACEINDEX = 0x00000400, + IO_FACEFLAGS = 0x00000800, + IO_FACECOLOR = 0x00001000, + IO_FACEQUALITY = 0x00002000, + IO_FACENORMAL = 0x00004000, + IO_FACECURVDIR = 0x00008000, + IO_FACEATTRIB = 0x00010000, - IO_EDGEINDEX = 0x00020000, - IO_EDGEQUALITY = 0x00040000, - IO_EDGECOLOR = 0x00080000, - IO_EDGEFLAGS = 0x00100000, - IO_EDGEATTRIB = 0x00200000, + IO_EDGEINDEX = 0x00020000, + IO_EDGEQUALITY = 0x00040000, + IO_EDGECOLOR = 0x00080000, + IO_EDGEFLAGS = 0x00100000, + IO_EDGEATTRIB = 0x00200000, - IO_WEDGCOLOR = 0x00400000, - IO_WEDGTEXCOORD = 0x00800000, - IO_WEDGTEXMULTI = 0x01000000, // when textrue index is explicit - IO_WEDGNORMAL = 0x02000000, + IO_WEDGCOLOR = 0x00400000, + IO_WEDGTEXCOORD = 0x00800000, + IO_WEDGTEXMULTI = 0x01000000, // when texture index is explicit + IO_WEDGNORMAL = 0x02000000, + + IO_ALL_ATTRIB = 0x03FFFFFF, IO_BITPOLYGONAL = 0x04000000, // loads explicit polygonal mesh @@ -202,28 +217,25 @@ namespace nanoply template - void AddVertexAttribDescriptor(std::string& name, PlyType type, void* ptr) + void AddVertexAttribDescriptor(const std::string& name, PlyType type, void* ptr) { - vertexAttrib.push_back(new DataDescriptor(name, ptr)); - vertexAttribProp.push_back(PlyProperty(type, name)); + AddAttribDescriptor(name, type, ptr, vertexAttrib, vertexAttribProp); + } + + template + void AddEdgeAttribDescriptor(const std::string& name, PlyType type, void* ptr) + { + AddAttribDescriptor(name, type, ptr, edgeAttrib, edgeAttribProp); } template - void AddEdgeAttribDescriptor(std::string& name, PlyType type, void* ptr) + void AddFaceAttribDescriptor(const std::string& name, PlyType type, void* ptr) { - edgeAttrib.push_back(new DataDescriptor(name, ptr)); - edgeAttribProp.push_back(PlyProperty(type, name)); + AddAttribDescriptor(name, type, ptr, faceAttrib, faceAttribProp); } template - void AddFaceAttribDescriptor(std::string& name, PlyType type, void* ptr) - { - faceAttrib.push_back(new DataDescriptor(name, ptr)); - faceAttribProp.push_back(PlyProperty(type, name)); - } - - template - void AddMeshAttribDescriptor(std::string& nameAttrib, std::string& nameProp, PlyType type, void* ptr) + void AddMeshAttribDescriptor(const std::string& nameAttrib, std::string& nameProp, PlyType type, void* ptr) { meshAttrib[nameAttrib].push_back(new DataDescriptor(nameProp, ptr)); meshAttribProp[nameAttrib].push_back(PlyProperty(type, nameProp)); @@ -246,18 +258,669 @@ namespace nanoply } } } + + bool CreateVertexAttribDescriptor(const PointerToAttribute* ptr) + { + return CreateAttribDescriptor(ptr, vertexAttrib, vertexAttribProp); + } + + bool CreateEdgeAttribDescriptor(const PointerToAttribute* ptr) + { + return CreateAttribDescriptor(ptr, edgeAttrib, edgeAttribProp); + } + + bool CreateFaceAttribDescriptor(const PointerToAttribute* ptr) + { + return CreateAttribDescriptor(ptr, faceAttrib, faceAttribProp); + } + + bool AddVertexAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem) + { + return AddCustomAttrib<0>(m, ptrAttrib, elem, vertexAttrib); + } + + bool AddEdgeAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem) + { + return AddCustomAttrib<1>(m, ptrAttrib, elem, vertexAttrib); + } + + bool AddFaceAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem) + { + return AddCustomAttrib<2>(m, ptrAttrib, elem, vertexAttrib); + } + + + + private: + + const std::vector pointSuffix = { "x", "y", "z", "w" }; + const std::vector colorSuffix = { "r", "g", "b", "a" }; + const std::map pointSuffixMap = { { "x", 0 },{ "y", 1 },{ "z", 2 },{ "w", 3 } }; + const std::map colorSuffixMap = { {"r", 0},{ "g", 1 },{ "b", 2 },{ "a", 3 } }; + const std::string separator = std::string("@_.#$>"); + + template + void AddAttribDescriptor(const std::string& name, PlyType type, void* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) + { + attrib.push_back(new DataDescriptor(name, ptr)); + attribProp.push_back(PlyProperty(type, name)); + } + + template + void AddScalarAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) + { + AddAttribDescriptor(ptr->_name, getEntity(), ptr->_handle->DataBegin(), attrib, attribProp); + } + + template + void AddPointAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) + { + int size = typename Container::Dimension; + std::string name(ptr->_name); + Container* tmpPtr = (Container*)ptr->_handle->DataBegin(); + for (int i = 0 ; i < size; i++) + AddAttribDescriptor((name + "." + pointSuffix[i]), getEntity(), &(*tmpPtr)[i], attrib, attribProp); + } + + template + void AddColorAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) + { + int size = typename Container::Dimension; + std::string name(ptr->_name); + Container* tmpPtr = (Container*)ptr->_handle->DataBegin(); + for (int i = 0; i < size; i++) + AddAttribDescriptor((name + "." + colorSuffix[i]), getEntity(), &(*tmpPtr)[i], attrib, attribProp); + } + + template + void AddListAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) + { + AddAttribDescriptor(ptr->_name, getEntityList(), ptr->_handle->DataBegin(), attrib, attribProp); + } + + bool CreateAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) + { + if (ptr->_type == std::type_index(typeid(unsigned char))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(char))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(unsigned short))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(short))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(unsigned int))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(int))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(float))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(double))) + AddScalarAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point2s))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point2i))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point2f))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point2d))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point3s))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point3i))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point3f))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point3d))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point4s))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point4i))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point4f))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Point4d))) + AddPointAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Color4b))) + AddColorAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Color4f))) + AddColorAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Color4d))) + AddColorAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(vcg::Color4d))) + AddColorAttribDescriptor(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor, unsigned char>(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor,char>(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor, unsigned short>(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor, short>(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor, unsigned int>(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor, int>(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor, float>(ptr, attrib, attribProp); + else if (ptr->_type == std::type_index(typeid(std::vector))) + AddListAttribDescriptor, double>(ptr, attrib, attribProp); + else + return false; + return true; + } + + + template + void AddScalarAttrib(MeshType& m, const std::string& name, PlyType& type) + { + if (ActionType == 0) //vertex + { + auto h = vcg::tri::Allocator::GetPerVertexAttribute(m, name); + AddVertexAttribDescriptor(name, type, h._handle->DataBegin()); + } + else if (ActionType == 1) //Edge + { + auto h = vcg::tri::Allocator::GetPerEdgeAttribute(m, name); + AddEdgeAttribDescriptor(name, type, h._handle->DataBegin()); + } + else if (ActionType == 2) //Face + { + auto h = vcg::tri::Allocator::GetPerFaceAttribute(m, name); + AddFaceAttribDescriptor(name, type, h._handle->DataBegin()); + } + } + + template + void AddPointAttrib(MeshType& m, const std::string& name, std::vector& prop) + { + if (ActionType == 0) //vertex + { + auto h = vcg::tri::Allocator::GetPerVertexAttribute(m, name); + for (int i = 0; i < prop.size(); i++) + AddVertexAttribDescriptor(prop[i].name, prop[i].type, &h[0][i]); + } + else if (ActionType == 1) //Edge + { + auto h = vcg::tri::Allocator::GetPerEdgeAttribute(m, name); + for (int i = 0; i < prop.size(); i++) + AddEdgeAttribDescriptor(prop[i].name, prop[i].type, &h[0][i]); + } + else if (ActionType == 2) //Face + { + auto h = vcg::tri::Allocator::GetPerFaceAttribute(m, name); + for (int i = 0; i < prop.size(); i++) + AddFaceAttribDescriptor(prop[i].name, prop[i].type, &h[0][i]); + } + } + + + template + void AddListAttrib(MeshType& m, const std::string& name, PlyType& type) + { + if (ActionType == 0) //vertex + { + auto h = vcg::tri::Allocator::GetPerVertexAttribute(m, name); + AddVertexAttribDescriptor(name, type, h._handle->DataBegin()); + } + else if (ActionType == 1) //Edge + { + auto h = vcg::tri::Allocator::GetPerEdgeAttribute(m, name); + AddEdgeAttribDescriptor(name, type, h._handle->DataBegin()); + } + else if (ActionType == 2) //Face + { + auto h = vcg::tri::Allocator::GetPerFaceAttribute(m, name); + AddFaceAttribDescriptor(name, type, h._handle->DataBegin()); + } + } + + + template + bool AddCustomAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem, ElementDescriptor::PropertyDescriptor& attrib) + { + //Custom attribute with already a data descriptor + std::set validCustomAttrib; + for (int i = 0; i < attrib.size(); i++) + { + if (attrib[i]->base == NULL) + { + std::set::iterator ai; + for (ai = ptrAttrib.begin(); ai != ptrAttrib.end(); ++ai) + { + if (attrib[i]->name == (*ai)._name) + { + attrib[i]->base = ai->_handle->DataBegin(); + validCustomAttrib.insert(attrib[i]->name); + break; + } + } + } + else + validCustomAttrib.insert(attrib[i]->name); + } + //Get custom properties without a data descriptor + std::map, int>> customAttribName; + std::vector attribName((*elem).propVec.size()); + for (int i = 0; i < (*elem).propVec.size(); i++) + { + if ((*elem).propVec[i].elem == NNP_UNKNOWN_ENTITY) + { + if (validCustomAttrib.find((*elem).propVec[i].name) == validCustomAttrib.end()) + { + std::size_t found = (*elem).propVec[i].name.find_first_of(separator); + if (found != std::string::npos) + { + attribName[i] = (*elem).propVec[i].name.substr(0, found); + std::string suffix = (*elem).propVec[i].name.substr(found+1); + std::map::const_iterator it1, it2; + it1 = pointSuffixMap.find(suffix); + it2 = colorSuffixMap.find(suffix); + if (it1 != pointSuffixMap.cend()) + customAttribName[attribName[i]].second |= (1 << (*it1).second); + else if (it2 != colorSuffixMap.cend()) + customAttribName[attribName[i]].second |= (1 << ((*it2).second + 4)); + } + else + attribName[i] = (*elem).propVec[i].name; + customAttribName[attribName[i]].first.push_back((*elem).propVec[i]); + + } + } + } + //Create the attribute and the data descriptor + std::map, int>>::iterator mapIter; + for (mapIter = customAttribName.begin(); mapIter != customAttribName.end(); mapIter++) + { + unsigned int bitType = 0; + std::vector tempProp((*mapIter).second.first.size()); + int checkMask = (1 << (*mapIter).second.first.size()) - 1; + for (int i = 0; i < (*mapIter).second.first.size(); i++) + { + PlyProperty& p = (*mapIter).second.first[i]; + bitType |= p.type; + std::size_t found = p.name.find_first_of(separator); + if (found != std::string::npos) + { + std::string suffix = p.name.substr(found + 1); + if ((*mapIter).second.second == checkMask) + tempProp[(*pointSuffixMap.find(suffix)).second] = p; + else if ((*mapIter).second.second == (checkMask << 4)) + tempProp[(*colorSuffixMap.find(suffix)).second] = p; + else + tempProp[i] = p; + } + else + tempProp[i] = p; + } + unsigned int r = (bitType & (~tempProp[0].type)); + if (tempProp.size() > 1 && ((bitType & (~tempProp[0].type)) == 0)) + { + if (tempProp.size() == 2) + { + switch (tempProp[0].type) + { + case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_INT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_INT16: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_INT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_UINT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_UINT16: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_UINT32: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + } + } + else if (tempProp.size() == 3) + { + switch (tempProp[0].type) + { + case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_INT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_INT16: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_INT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_UINT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_UINT16: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_UINT32: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + } + } + else if (tempProp.size() == 4 && (*mapIter).second.second != (checkMask << 4)) + { + switch (tempProp[0].type) + { + case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_INT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_INT16: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_INT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_UINT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_UINT16: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + case NNP_UINT32: AddPointAttrib>(m, (*mapIter).first, tempProp); break; + } + } + else if (tempProp.size() == 4) + { + switch (tempProp[0].type) + { + case NNP_INT8: + case NNP_INT16: + case NNP_INT32: + case NNP_UINT16: + case NNP_UINT32: + case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; + case NNP_UINT8: AddPointAttrib(m, (*mapIter).first, tempProp); break; + } + } + } + else + { + for (int i = 0; i < tempProp.size(); i++) + { + switch (tempProp[i].type) + { + case NNP_FLOAT32: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_FLOAT64: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_INT8: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_INT16: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_INT32: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_UINT8: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_UINT16: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_UINT32: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_UINT32: + case NNP_LIST_INT8_UINT32: AddListAttrib, unsigned int>(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_INT32: + case NNP_LIST_INT8_INT32: AddListAttrib, int>(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_FLOAT32: + case NNP_LIST_INT8_FLOAT32: AddListAttrib, float>(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_FLOAT64: + case NNP_LIST_INT8_FLOAT64: AddListAttrib, double>(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_UINT8: + case NNP_LIST_INT8_UINT8: AddListAttrib, unsigned char>(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_INT8: + case NNP_LIST_INT8_INT8: AddListAttrib, char>(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_UINT16: + case NNP_LIST_INT8_UINT16: AddListAttrib, unsigned short>(m, tempProp[i].name, tempProp[i].type); break; + case NNP_LIST_UINT8_INT16: + case NNP_LIST_INT8_INT16: AddListAttrib, short>(m, tempProp[i].name, tempProp[i].type); break; + } + } + } + } + return true; + } + + }; + template + struct OcfManager + { + typedef typename T::VertexType VType; + typedef typename T::FaceType FType; + typedef typename T::EdgeType EType; + + + template >::value> + static unsigned int EnableVertexOcf(typename T::VertContainer& cont, unsigned int mask) { + return 0; + } + + template <> + static unsigned int EnableVertexOcf(typename T::VertContainer& cont, unsigned int mask ) + { + unsigned int enabledMask = 0; + if ((mask & BitMask::IO_VERTNORMAL) && VType::HasNormalOcf() && !cont.IsNormalEnabled()) + { + cont.EnableNormal(); + enabledMask |= BitMask::IO_VERTNORMAL; + } + if ((mask & BitMask::IO_VERTCOLOR) && VType::HasColorOcf() && !cont.IsColorEnabled()) + { + cont.EnableColor(); + enabledMask |= BitMask::IO_VERTCOLOR; + } + if ((mask & BitMask::IO_VERTQUALITY) && VType::HasQualityOcf() && !cont.IsQualityEnabled()) + { + cont.EnableQuality(); + enabledMask |= BitMask::IO_VERTQUALITY; + } + if ((mask & BitMask::IO_VERTCURV) && VType::HasCurvatureOcf() && !cont.IsCurvatureEnabled()) + { + cont.EnableCurvature(); + enabledMask |= BitMask::IO_VERTCURV; + } + if ((mask & BitMask::IO_VERTCURVDIR) && VType::HasCurvatureDirOcf() && !cont.IsCurvatureDirEnabled()) + { + cont.EnableCurvatureDir(); + enabledMask |= BitMask::IO_VERTCURVDIR; + } + if ((mask & BitMask::IO_VERTRADIUS) && VType::HasRadiusOcf() && !cont.IsRadiusEnabled()) + { + cont.EnableRadius(); + enabledMask |= BitMask::IO_VERTRADIUS; + } + if ((mask & BitMask::IO_VERTTEXCOORD) && VType::HasTexCoordOcf() && !cont.IsTexCoordEnabled()) + { + cont.EnableTexCoord(); + enabledMask |= BitMask::IO_VERTTEXCOORD; + } + return enabledMask; + }; + + + template >::value> + static unsigned int EnableFaceOcf(typename T::FaceContainer& cont, unsigned int mask) { + return 0; + } + + template <> + static unsigned int EnableFaceOcf(typename T::FaceContainer& cont, unsigned int mask) + { + unsigned int enabledMask = 0; + if ((mask & BitMask::IO_FACENORMAL) && FType::HasNormalOcf() && !cont.IsNormalEnabled()) + { + cont.EnableNormal(); + enabledMask |= BitMask::IO_FACENORMAL; + } + if ((mask & BitMask::IO_FACECOLOR) && FType::HasColorOcf() && !cont.IsColorEnabled()) + { + cont.EnableColor(); + enabledMask |= BitMask::IO_FACECOLOR; + } + if ((mask & BitMask::IO_FACEQUALITY) && FType::HasQualityOcf() && !cont.IsQualityEnabled()) + { + cont.EnableQuality(); + enabledMask |= BitMask::IO_FACEQUALITY; + } + if ((mask & BitMask::IO_FACECURVDIR) && FType::HasCurvatureDirOcf() && !cont.IsCurvatureDirEnabled()) + { + cont.EnableCurvatureDir(); + enabledMask |= BitMask::IO_FACECURVDIR; + } + if ((mask & BitMask::IO_WEDGCOLOR) && FType::HasWedgeColorOcf() && !cont.IsWedgeColorEnabled()) + { + cont.EnableWedgeColor(); + enabledMask |= BitMask::IO_WEDGCOLOR; + } + if ((mask & BitMask::IO_WEDGNORMAL) && FType::HasWedgeNormalOcf() && !cont.IsWedgeNormalEnabled()) + { + cont.EnableWedgeNormal(); + enabledMask |= BitMask::IO_WEDGNORMAL; + } + if ((mask & BitMask::IO_WEDGTEXCOORD) && FType::HasWedgeTexCoordOcf() && !cont.IsWedgeTexCoordEnabled()) + { + cont.EnableWedgeTexCoord(); + enabledMask |= BitMask::IO_WEDGTEXCOORD; + } + if ((mask & BitMask::IO_WEDGTEXMULTI) && FType::HasWedgeTexCoordOcf()) + { + if (!cont.IsWedgeTexCoordEnabled()) + cont.EnableWedgeTexCoord(); + enabledMask |= BitMask::IO_WEDGTEXMULTI; + } + return enabledMask; + }; + + + + template >::value> + static unsigned int VertexOcfMask(typename T::VertContainer& cont) { + return 0; + } + + template <> + static unsigned int VertexOcfMask(typename T::VertContainer& cont) + { + unsigned int enabledMask = 0; + if (VType::HasNormalOcf() && cont.IsNormalEnabled()) + enabledMask |= BitMask::IO_VERTNORMAL; + if (VType::HasColorOcf() && cont.IsColorEnabled()) + enabledMask |= BitMask::IO_VERTCOLOR; + if (VType::HasQualityOcf() && cont.IsQualityEnabled()) + enabledMask |= BitMask::IO_VERTQUALITY; + if (VType::HasCurvatureOcf() && cont.IsCurvatureEnabled()) + enabledMask |= BitMask::IO_VERTCURV; + if (VType::HasCurvatureDirOcf() && cont.IsCurvatureDirEnabled()) + enabledMask |= BitMask::IO_VERTCURVDIR; + if (VType::HasRadiusOcf() && cont.IsRadiusEnabled()) + enabledMask |= BitMask::IO_VERTRADIUS; + if (VType::HasTexCoordOcf() && cont.IsTexCoordEnabled()) + enabledMask |= BitMask::IO_VERTTEXCOORD; + return enabledMask; + }; + + + template >::value> + static unsigned int FaceOcfMask(typename T::FaceContainer& cont) { + return 0; + } + + template <> + static unsigned int FaceOcfMask(typename T::FaceContainer& cont) + { + unsigned int enabledMask = 0; + if (FType::HasNormalOcf() && cont.IsNormalEnabled()) + enabledMask |= BitMask::IO_FACENORMAL; + if (FType::HasColorOcf() && cont.IsColorEnabled()) + enabledMask |= BitMask::IO_FACECOLOR; + if (FType::HasQualityOcf() && cont.IsQualityEnabled()) + enabledMask |= BitMask::IO_FACEQUALITY; + if (FType::HasCurvatureDirOcf() && cont.IsCurvatureDirEnabled()) + enabledMask |= BitMask::IO_FACECURVDIR; + if (FType::HasWedgeColorOcf() && cont.IsWedgeColorEnabled()) + enabledMask |= BitMask::IO_WEDGCOLOR; + if (FType::HasWedgeNormalOcf() && cont.IsWedgeNormalEnabled()) + enabledMask |= BitMask::IO_WEDGNORMAL; + if (FType::HasWedgeTexCoordOcf() && cont.IsWedgeTexCoordEnabled()) + { + enabledMask |= BitMask::IO_WEDGTEXCOORD; + enabledMask |= BitMask::IO_WEDGTEXMULTI; + } + return enabledMask; + }; + + }; + + + + static unsigned int GetFileBitMask(nanoply::Info& info) + { + unsigned int mask = 0; + for (int j = 0; j < info.elemVec.size(); j++) + { + PlyElement& elem = info.elemVec[j]; + if (elem.plyElem == PlyElemEntity::NNP_VERTEX_ELEM) + { + for (int i = 0; i < elem.propVec.size(); i++) + { + switch (elem.propVec[i].elem) + { + case NNP_PXYZ: mask |= BitMask::IO_VERTCOORD; break; + case NNP_NXYZ: mask |= BitMask::IO_VERTNORMAL; break; + case NNP_CRGB: + case NNP_CRGBA: mask |= BitMask::IO_VERTCOLOR; break; + case NNP_BITFLAG: mask |= BitMask::IO_VERTFLAGS; break; + case NNP_QUALITY: mask |= BitMask::IO_VERTQUALITY; break; + case NNP_DENSITY: mask |= BitMask::IO_VERTRADIUS; break; + case NNP_TEXTURE2D: + case NNP_TEXTURE3D: mask |= BitMask::IO_VERTTEXCOORD; break; + case NNP_KH: + case NNP_KG: mask |= BitMask::IO_VERTCURV; break; + case NNP_K1: + case NNP_K2: + case NNP_K1DIR: + case NNP_K2DIR: mask |= BitMask::IO_VERTCURVDIR; break; + case NNP_UNKNOWN_ENTITY: mask |= BitMask::IO_VERTATTRIB; break; + } + } + } + else if (elem.plyElem == PlyElemEntity::NNP_EDGE_ELEM) + { + for (int i = 0; i < elem.propVec.size(); i++) + { + switch (elem.propVec[i].elem) + { + case NNP_EDGE_V1: + case NNP_EDGE_V2: mask |= BitMask::IO_EDGEINDEX; break; + case NNP_CRGB: + case NNP_CRGBA: mask |= BitMask::IO_EDGECOLOR; break; + case NNP_BITFLAG: mask |= BitMask::IO_EDGEFLAGS; break; + case NNP_QUALITY: mask |= BitMask::IO_EDGEQUALITY; break; + case NNP_UNKNOWN_ENTITY: mask |= BitMask::IO_EDGEATTRIB; break; + } + } + } + else if (elem.plyElem == PlyElemEntity::NNP_FACE_ELEM) + { + for (int i = 0; i < elem.propVec.size(); i++) + { + switch (elem.propVec[i].elem) + { + case NNP_FACE_VERTEX_LIST: mask |= BitMask::IO_FACEINDEX; break; + case NNP_NXYZ: mask |= BitMask::IO_FACENORMAL; break; + case NNP_CRGB: + case NNP_CRGBA: mask |= BitMask::IO_FACECOLOR; break; + case NNP_BITFLAG: mask |= BitMask::IO_FACEFLAGS; break; + case NNP_QUALITY: mask |= BitMask::IO_FACEQUALITY; break; + case NNP_K1: + case NNP_K2: + case NNP_K1DIR: + case NNP_K2DIR: mask |= BitMask::IO_FACECURVDIR; break; + case NNP_FACE_WEDGE_COLOR: mask |= BitMask::IO_WEDGCOLOR; break; + case NNP_FACE_WEDGE_NORMAL: mask |= BitMask::IO_WEDGNORMAL; break; + case NNP_FACE_WEDGE_TEX: mask |= BitMask::IO_WEDGTEXCOORD; break; + case NNP_TEXTUREINDEX: mask |= BitMask::IO_WEDGTEXMULTI; break; + case NNP_UNKNOWN_ENTITY: mask |= BitMask::IO_FACEATTRIB; break; + } + } + } + else if (elem.plyElem == PlyElemEntity::NNP_UNKNOWN_ELEM) + { + if (elem.name == "camera") + mask |= BitMask::IO_CAMERA; + else + mask |= BitMask::IO_MESHATTRIB; + } + } + return mask; + }; + + static int LoadModel(const char* filename, MeshType& mesh, unsigned int bitMask, CustomAttributeDescriptor& custom) { nanoply::Info info(filename); if (info.errInfo != nanoply::NNP_OK) return info.errInfo; - - //Camera + + unsigned int headerMask = GetFileBitMask(info); + bitMask &= headerMask; + unsigned int ocfVertexMask = OcfManager::EnableVertexOcf(mesh.vert, bitMask); + unsigned int ocfFaceMask = OcfManager::EnableFaceOcf(mesh.face, bitMask); + + //Camera ElementDescriptor cameraDescr(std::string("camera")); vcg::Point3 tra; vcg::Matrix44 rot; @@ -299,46 +962,82 @@ namespace nanoply vcg::tri::Allocator::AddVertices(mesh, count); if ((bitMask & BitMask::IO_VERTCOORD) && VertexType::HasCoord()) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_PXYZ, (*mesh.vert.begin()).P().V())); - if ((bitMask & BitMask::IO_VERTNORMAL) && vcg::tri::HasPerVertexNormal(mesh)) - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.vert.begin()).N().V())); - if ((bitMask & BitMask::IO_VERTCOLOR) && vcg::tri::HasPerVertexColor(mesh)) - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.vert.begin()).C().V())); - if ((bitMask & BitMask::IO_VERTQUALITY) && vcg::tri::HasPerVertexQuality(mesh)) - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.vert.begin()).Q())); + if ((bitMask & BitMask::IO_VERTNORMAL) && vcg::tri::HasPerVertexNormal(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTNORMAL) + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.vert.begin()).N().V())); + else + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.vert.begin()).N().V())); + } + if ((bitMask & BitMask::IO_VERTCOLOR) && vcg::tri::HasPerVertexColor(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTCOLOR) + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.vert.begin()).C().V())); + else + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.vert.begin()).C().V())); + } + if ((bitMask & BitMask::IO_VERTQUALITY) && vcg::tri::HasPerVertexQuality(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTQUALITY) + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.vert.begin()).Q())); + else + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.vert.begin()).Q())); + } if ((bitMask & BitMask::IO_VERTFLAGS) && vcg::tri::HasPerVertexFlags(mesh)) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_BITFLAG, &(*mesh.vert.begin()).Flags())); - if ((bitMask & BitMask::IO_VERTRADIUS) && vcg::tri::HasPerVertexRadius(mesh)) - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_DENSITY, &(*mesh.vert.begin()).R())); - if ((bitMask & BitMask::IO_VERTTEXCOORD) && vcg::tri::HasPerVertexTexCoord(mesh)) - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V())); - if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) + if ((bitMask & BitMask::IO_VERTRADIUS) && vcg::tri::HasPerVertexRadius(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTRADIUS) + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_DENSITY, &(*mesh.vert.begin()).R())); + else + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_DENSITY, &(*mesh.vert.begin()).R())); + } + if ((bitMask & BitMask::IO_VERTTEXCOORD) && vcg::tri::HasPerVertexTexCoord(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V())); + else + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V())); + } + if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) { - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); + if (ocfVertexMask & BitMask::IO_VERTCURV) + { + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); + } + else + { + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); + } } if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) { - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.vert.begin()).K1())); - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.vert.begin()).K2())); - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.vert.begin()).PD1().V())); - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.vert.begin()).PD2().V())); - } - if ((bitMask & BitMask::IO_VERTATTRIB) && custom.vertexAttrib.size() > 0) - { - for (int i = 0; i < custom.vertexAttrib.size(); i++) - { - std::set::iterator ai; - for (ai = mesh.vert_attr.begin(); ai != mesh.vert_attr.end(); ++ai) - { - if ((*custom.vertexAttrib[i]).name == (*ai)._name) - { - custom.vertexAttrib[i]->base = ai->_handle->DataBegin(); - break; - } - } - vertexDescr.dataDescriptor.push_back(custom.vertexAttrib[i]); - } - } + if (ocfVertexMask & BitMask::IO_VERTCURVDIR) + { + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.vert.begin()).K1())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.vert.begin()).K2())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.vert.begin()).PD1().V())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.vert.begin()).PD2().V())); + } + else + { + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.vert.begin()).K1())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.vert.begin()).K2())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.vert.begin()).PD1().V())); + vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.vert.begin()).PD2().V())); + } + } + if (bitMask & BitMask::IO_VERTATTRIB) + { + custom.AddVertexAttrib(mesh, mesh.vert_attr, info.GetVertexElement()); + for (int i = 0; i < custom.vertexAttrib.size(); i++) + { + if ((*custom.vertexAttrib[i]).base != NULL) + vertexDescr.dataDescriptor.push_back(custom.vertexAttrib[i]); + } + } } //Edge @@ -362,22 +1061,15 @@ namespace nanoply edgeDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.edge.begin()).C().V())); if ((bitMask & BitMask::IO_EDGEFLAGS) && vcg::tri::HasPerEdgeFlags(mesh)) edgeDescr.dataDescriptor.push_back(new DataDescriptor(NNP_BITFLAG, &(*mesh.edge.begin()).Flags())); - if ((bitMask & BitMask::IO_EDGEATTRIB) && custom.edgeAttrib.size() > 0) - { + if (bitMask & BitMask::IO_EDGEATTRIB) + { + custom.AddEdgeAttrib(mesh, mesh.edge_attr, info.GetEdgeElement()); for (int i = 0; i < custom.edgeAttrib.size(); i++) { - std::set::iterator ai; - for (ai = mesh.edge_attr.begin(); ai != mesh.edge_attr.end(); ++ai) - { - if ((*custom.edgeAttrib[i]).name == (*ai)._name) - { - custom.edgeAttrib[i]->base = ai->_handle->DataBegin(); - break; - } - } - edgeDescr.dataDescriptor.push_back(custom.edgeAttrib[i]); + if ((*custom.edgeAttrib[i]).base != NULL) + edgeDescr.dataDescriptor.push_back(custom.edgeAttrib[i]); } - } + } } //Face @@ -385,7 +1077,7 @@ namespace nanoply FaceType::Name(nameList); ElementDescriptor faceDescr(NNP_FACE_ELEM); count = info.GetFaceCount(); - std::vector faceIndex; + std::vector> faceIndex; std::vector> wedgeTexCoord; if (nameList.size() > 0 && count > 0) { @@ -393,52 +1085,83 @@ namespace nanoply if ((bitMask & BitMask::IO_FACEINDEX) && FaceType::HasVertexRef()) { faceIndex.resize(count); - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_VERTEX_LIST, (*faceIndex.begin()).V())); + faceDescr.dataDescriptor.push_back(new DataDescriptor,0, unsigned int>(NNP_FACE_VERTEX_LIST, &faceIndex[0])); } if ((bitMask & BitMask::IO_FACEFLAGS) && vcg::tri::HasPerFaceFlags(mesh)) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_BITFLAG, &(*mesh.face.begin()).Flags())); - if ((bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh)) - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.face.begin()).C().V())); - if ((bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh)) - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.face.begin()).Q())); - if ((bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh)) - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.face.begin()).N().V())); - if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerFaceCurvatureDir(mesh)) + if ((bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh)) + { + if (ocfFaceMask & BitMask::IO_FACECOLOR) + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.face.begin()).C().V())); + else + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.face.begin()).C().V())); + } + if ((bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh)) + { + if (ocfFaceMask & BitMask::IO_FACEQUALITY) + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.face.begin()).Q())); + else + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.face.begin()).Q())); + } + if ((bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh)) + { + if (ocfFaceMask & BitMask::IO_FACENORMAL) + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.face.begin()).N().V())); + else + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.face.begin()).N().V())); + } + if ((bitMask & BitMask::IO_FACECURVDIR) && vcg::tri::HasPerFaceCurvatureDir(mesh)) { - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.face.begin()).K1())); - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.face.begin()).K2())); - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.face.begin()).PD1().V())); - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.face.begin()).PD2().V())); + if (ocfFaceMask & BitMask::IO_FACECURVDIR) + { + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.face.begin()).K1())); + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.face.begin()).K2())); + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.face.begin()).PD1().V())); + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.face.begin()).PD2().V())); + } + else + { + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.face.begin()).K1())); + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.face.begin()).K2())); + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.face.begin()).PD1().V())); + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.face.begin()).PD2().V())); + } } if (((bitMask & BitMask::IO_WEDGTEXCOORD) || (bitMask & BitMask::IO_WEDGTEXMULTI)) && vcg::tri::HasPerWedgeTexCoord(mesh)) { wedgeTexCoord.resize(count); faceDescr.dataDescriptor.push_back(new DataDescriptor, 6, FaceTexScalar>(NNP_FACE_WEDGE_TEX, (*wedgeTexCoord.begin()).V())); } - if ((bitMask & BitMask::IO_WEDGTEXMULTI) && vcg::tri::HasPerWedgeTexCoord(mesh)) - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N())); - if ((bitMask & BitMask::IO_WEDGCOLOR) && vcg::tri::HasPerWedgeColor(mesh)) - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V())); - if ((bitMask & BitMask::IO_WEDGNORMAL) && vcg::tri::HasPerWedgeNormal(mesh)) - faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V())); - if ((bitMask & BitMask::IO_FACEATTRIB) && custom.faceAttrib.size() > 0) - { - for (int i = 0; i < custom.faceAttrib.size(); i++) - { - std::set::iterator ai; - for (ai = mesh.face_attr.begin(); ai != mesh.face_attr.end(); ++ai) - { - if ((*custom.faceAttrib[i]).name == (*ai)._name) - { - custom.faceAttrib[i]->base = ai->_handle->DataBegin(); - break; - } - } - faceDescr.dataDescriptor.push_back(custom.faceAttrib[i]); - - } - } - + if ((bitMask & BitMask::IO_WEDGTEXMULTI) && vcg::tri::HasPerWedgeTexCoord(mesh)) + { + if (ocfFaceMask & BitMask::IO_WEDGTEXMULTI) + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N())); + else + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N())); + } + if ((bitMask & BitMask::IO_WEDGCOLOR) && vcg::tri::HasPerWedgeColor(mesh)) + { + if (ocfFaceMask & BitMask::IO_WEDGCOLOR) + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V())); + else + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V())); + } + if ((bitMask & BitMask::IO_WEDGNORMAL) && vcg::tri::HasPerWedgeNormal(mesh)) + { + if (ocfFaceMask & BitMask::IO_WEDGNORMAL) + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V())); + else + faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V())); + } + if (bitMask & BitMask::IO_FACEATTRIB) + { + custom.AddFaceAttrib(mesh, mesh.face_attr, info.GetFaceElement()); + for (int i = 0; i < custom.faceAttrib.size(); i++) + { + if ((*custom.faceAttrib[i]).base != NULL) + faceDescr.dataDescriptor.push_back(custom.faceAttrib[i]); + } + } } std::vector meshDescr; @@ -468,18 +1191,70 @@ namespace nanoply mesh.shot.SetViewPoint(tra); mesh.shot.Extrinsics.SetRot(rot); + bool triangleMesh = true; for (int i = 0; i < faceIndex.size(); i++) - for (int j = 0; j < 3; j++) - mesh.face[i].V(j) = &mesh.vert[faceIndex[i][j]]; - for (int i = 0; i < wedgeTexCoord.size(); i++) + if (faceIndex[i].size() > 3) + triangleMesh = false; + + if (!triangleMesh && !vcg::tri::HasPolyInfo(mesh)) { - for (int j = 0; j < 3; j++) + bool hasFaceFlags = (bitMask & BitMask::IO_FACEFLAGS) && vcg::tri::HasPerFaceFlags(mesh); + bool hasFaceColor = (bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh); + bool hasFaceQuality = (bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh); + bool hasFaceNormal = (bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh); + for (int i = 0; i < faceIndex.size(); i++) { - mesh.face[i].WT(j).U() = wedgeTexCoord[i][j * 2]; - mesh.face[i].WT(j).V() = wedgeTexCoord[i][j * 2 + 1]; + if (faceIndex[i].size() >= 3) + { + for (int j = 0; j < 3; j++) + mesh.face[i].V(j) = &mesh.vert[faceIndex[i][j]]; + if (hasFaceFlags) + mesh.face[i].SetF(2); + FaceIterator fi = vcg::tri::Allocator::AddFaces(mesh, faceIndex[i].size() - 3); + for (int j = 3; j < faceIndex[i].size(); j++) + { + (*fi).V(0) = &mesh.vert[faceIndex[i][0]]; + (*fi).V(1) = &mesh.vert[faceIndex[i][j - 1]]; + (*fi).V(2) = &mesh.vert[faceIndex[i][j]]; + if (hasFaceFlags) + { + (*fi).SetFlags(mesh.face[i].Flags()); + (*fi).SetF(0); + if (j == faceIndex[i].size() - 1) + (*fi).ClearF(2); + } + if (hasFaceColor) + (*fi).C() = mesh.face[i].C(); + if (hasFaceQuality) + (*fi).Q() = mesh.face[i].Q(); + if (hasFaceNormal) + (*fi).N() = mesh.face[i].N(); + fi++; + } + } + else + mesh.face[i].V(0) = mesh.face[i].V(1) = mesh.face[i].V(2) = &mesh.vert[0]; } } - for (int i = 0; i < edgeIndex.size(); i++) + else + { + for (int i = 0; i < faceIndex.size(); i++) + { + mesh.face[i].Alloc(faceIndex[i].size()); + for (int j = 0; j < faceIndex[i].size(); j++) + mesh.face[i].V(j) = &mesh.vert[faceIndex[i][j]]; + } + for (int i = 0; i < wedgeTexCoord.size(); i++) + { + for (int j = 0; j < 3; j++) + { + mesh.face[i].WT(j).U() = wedgeTexCoord[i][j * 2]; + mesh.face[i].WT(j).V() = wedgeTexCoord[i][j * 2 + 1]; + } + } + } + + for (int i = 0; i < edgeIndex.size(); i++) { mesh.edge[i].V(0) = &mesh.vert[edgeIndex[i].X()]; mesh.edge[i].V(1) = &mesh.vert[edgeIndex[i].Y()]; @@ -510,6 +1285,9 @@ namespace nanoply static bool SaveModel(const char* filename, MeshType& mesh, unsigned int bitMask, CustomAttributeDescriptor& custom, bool binary) { + unsigned int ocfVertexMask = OcfManager::VertexOcfMask(mesh.vert); + unsigned int ocfFaceMask = OcfManager::FaceOcfMask(mesh.face); + //Camera std::vector cameraProp; ElementDescriptor cameraDescr(std::string("camera")); @@ -526,62 +1304,121 @@ namespace nanoply PushDescriport(cameraProp, cameraDescr, std::string("y_axisx"), &rot[1][0]); PushDescriport(cameraProp, cameraDescr, std::string("y_axisy"), &rot[1][1]); PushDescriport(cameraProp, cameraDescr, std::string("y_axisz"), &rot[1][2]); - PushDescriport(cameraProp, cameraDescr, std::string("z_axisx"), &rot[2][0]); - PushDescriport(cameraProp, cameraDescr, std::string("z_axisy"), &rot[2][1]); - PushDescriport(cameraProp, cameraDescr, std::string("z_axisz"), &rot[2][2]); - PushDescriport(cameraProp, cameraDescr, std::string("focal"), &mesh.shot.Intrinsics.FocalMm); - PushDescriport(cameraProp, cameraDescr, std::string("scalex"), &mesh.shot.Intrinsics.PixelSizeMm[0]); - PushDescriport(cameraProp, cameraDescr, std::string("scaley"), &mesh.shot.Intrinsics.PixelSizeMm[1]); - PushDescriport(cameraProp, cameraDescr, std::string("centerx"), &mesh.shot.Intrinsics.CenterPx[0]); - PushDescriport(cameraProp, cameraDescr, std::string("centery"), &mesh.shot.Intrinsics.CenterPx[1]); - PushDescriport(cameraProp, cameraDescr, std::string("viewportx"), &mesh.shot.Intrinsics.ViewportPx[0]); - PushDescriport(cameraProp, cameraDescr, std::string("viewporty"), &mesh.shot.Intrinsics.ViewportPx[1]); - PushDescriport(cameraProp, cameraDescr, std::string("k1"), &mesh.shot.Intrinsics.k[0]); - PushDescriport(cameraProp, cameraDescr, std::string("k2"), &mesh.shot.Intrinsics.k[1]); - PushDescriport(cameraProp, cameraDescr, std::string("k3"), &mesh.shot.Intrinsics.k[2]); - PushDescriport(cameraProp, cameraDescr, std::string("k4"), &mesh.shot.Intrinsics.k[3]); - } + PushDescriport(cameraProp, cameraDescr, std::string("z_axisx"), &rot[2][0]); + PushDescriport(cameraProp, cameraDescr, std::string("z_axisy"), &rot[2][1]); + PushDescriport(cameraProp, cameraDescr, std::string("z_axisz"), &rot[2][2]); + PushDescriport(cameraProp, cameraDescr, std::string("focal"), &mesh.shot.Intrinsics.FocalMm); + PushDescriport(cameraProp, cameraDescr, std::string("scalex"), &mesh.shot.Intrinsics.PixelSizeMm[0]); + PushDescriport(cameraProp, cameraDescr, std::string("scaley"), &mesh.shot.Intrinsics.PixelSizeMm[1]); + PushDescriport(cameraProp, cameraDescr, std::string("centerx"), &mesh.shot.Intrinsics.CenterPx[0]); + PushDescriport(cameraProp, cameraDescr, std::string("centery"), &mesh.shot.Intrinsics.CenterPx[1]); + PushDescriport(cameraProp, cameraDescr, std::string("viewportx"), &mesh.shot.Intrinsics.ViewportPx[0]); + PushDescriport(cameraProp, cameraDescr, std::string("viewporty"), &mesh.shot.Intrinsics.ViewportPx[1]); + PushDescriport(cameraProp, cameraDescr, std::string("k1"), &mesh.shot.Intrinsics.k[0]); + PushDescriport(cameraProp, cameraDescr, std::string("k2"), &mesh.shot.Intrinsics.k[1]); + PushDescriport(cameraProp, cameraDescr, std::string("k3"), &mesh.shot.Intrinsics.k[2]); + PushDescriport(cameraProp, cameraDescr, std::string("k4"), &mesh.shot.Intrinsics.k[3]); + } - //Vertex - std::vector nameList; - VertexType::Name(nameList); - std::vector vertexProp; - ElementDescriptor vertexDescr(NNP_VERTEX_ELEM); - if (nameList.size() > 0 && mesh.vert.size() > 0) - { - if ((bitMask & BitMask::IO_VERTCOORD) && VertexType::HasCoord()) - PushDescriport(vertexProp, vertexDescr, NNP_PXYZ, (*mesh.vert.begin()).P().V()); - if ((bitMask & BitMask::IO_VERTNORMAL) && vcg::tri::HasPerVertexNormal(mesh)) - PushDescriport(vertexProp, vertexDescr, NNP_NXYZ, (*mesh.vert.begin()).N().V()); - if ((bitMask & BitMask::IO_VERTCOLOR) && vcg::tri::HasPerVertexColor(mesh)) - PushDescriport(vertexProp, vertexDescr, NNP_CRGBA, (*mesh.vert.begin()).C().V()); - if ((bitMask & BitMask::IO_VERTQUALITY) && vcg::tri::HasPerVertexQuality(mesh)) - PushDescriport(vertexProp, vertexDescr, NNP_QUALITY, &(*mesh.vert.begin()).Q()); - if ((bitMask & BitMask::IO_VERTFLAGS) && vcg::tri::HasPerVertexFlags(mesh)) - PushDescriport(vertexProp, vertexDescr, NNP_BITFLAG, &(*mesh.vert.begin()).Flags()); - if ((bitMask & BitMask::IO_VERTRADIUS) && vcg::tri::HasPerVertexRadius(mesh)) - PushDescriport(vertexProp, vertexDescr, NNP_DENSITY, &(*mesh.vert.begin()).R()); - if ((bitMask & BitMask::IO_VERTTEXCOORD) && vcg::tri::HasPerVertexTexCoord(mesh)) - PushDescriport(vertexProp, vertexDescr, NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V()); - if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) - { - PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); - PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); - } - if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) - { - PushDescriport(vertexProp, vertexDescr, NNP_K1, &(*mesh.vert.begin()).K1()); - PushDescriport(vertexProp, vertexDescr, NNP_K2, &(*mesh.vert.begin()).K2()); - PushDescriportList(vertexProp, vertexDescr, NNP_K1DIR, (*mesh.vert.begin()).PD1().V()); - PushDescriportList(vertexProp, vertexDescr, NNP_K2DIR, (*mesh.vert.begin()).PD2().V()); - } - if ((bitMask & BitMask::IO_VERTATTRIB) && custom.vertexAttrib.size() > 0) - { - for (int i = 0; i < custom.vertexAttrib.size(); i++) - { - vertexProp.push_back(custom.vertexAttribProp[i]); - vertexDescr.dataDescriptor.push_back(custom.vertexAttrib[i]); - } + //Vertex + std::vector nameList; + VertexType::Name(nameList); + std::vector vertexProp; + ElementDescriptor vertexDescr(NNP_VERTEX_ELEM); + if (nameList.size() > 0 && mesh.vert.size() > 0) + { + if ((bitMask & BitMask::IO_VERTCOORD) && VertexType::HasCoord()) + PushDescriport(vertexProp, vertexDescr, NNP_PXYZ, (*mesh.vert.begin()).P().V()); + if ((bitMask & BitMask::IO_VERTNORMAL) && vcg::tri::HasPerVertexNormal(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTNORMAL) + PushDescriport(vertexProp, vertexDescr, NNP_NXYZ, (*mesh.vert.begin()).N().V()); + else + PushDescriport(vertexProp, vertexDescr, NNP_NXYZ, (*mesh.vert.begin()).N().V()); + } + if ((bitMask & BitMask::IO_VERTCOLOR) && vcg::tri::HasPerVertexColor(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTCOLOR) + PushDescriport(vertexProp, vertexDescr, NNP_CRGBA, (*mesh.vert.begin()).C().V()); + else + PushDescriport(vertexProp, vertexDescr, NNP_CRGBA, (*mesh.vert.begin()).C().V()); + } + if ((bitMask & BitMask::IO_VERTQUALITY) && vcg::tri::HasPerVertexQuality(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTQUALITY) + PushDescriport(vertexProp, vertexDescr, NNP_QUALITY, &(*mesh.vert.begin()).Q()); + else + PushDescriport(vertexProp, vertexDescr, NNP_QUALITY, &(*mesh.vert.begin()).Q()); + } + if ((bitMask & BitMask::IO_VERTFLAGS) && vcg::tri::HasPerVertexFlags(mesh)) + PushDescriport(vertexProp, vertexDescr, NNP_BITFLAG, &(*mesh.vert.begin()).Flags()); + if ((bitMask & BitMask::IO_VERTRADIUS) && vcg::tri::HasPerVertexRadius(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTRADIUS) + PushDescriport(vertexProp, vertexDescr, NNP_DENSITY, &(*mesh.vert.begin()).R()); + else + PushDescriport(vertexProp, vertexDescr, NNP_DENSITY, &(*mesh.vert.begin()).R()); + } + if ((bitMask & BitMask::IO_VERTTEXCOORD) && vcg::tri::HasPerVertexTexCoord(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) + PushDescriport(vertexProp, vertexDescr, NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V()); + else + PushDescriport(vertexProp, vertexDescr, NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V()); + } + if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) + { + PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); + PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); + } + else + { + PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); + PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); + } + } + if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) + { + if (ocfVertexMask & BitMask::IO_VERTCURVDIR) + { + PushDescriport(vertexProp, vertexDescr, NNP_K1, &(*mesh.vert.begin()).K1()); + PushDescriport(vertexProp, vertexDescr, NNP_K2, &(*mesh.vert.begin()).K2()); + PushDescriportList(vertexProp, vertexDescr, NNP_K1DIR, (*mesh.vert.begin()).PD1().V()); + PushDescriportList(vertexProp, vertexDescr, NNP_K2DIR, (*mesh.vert.begin()).PD2().V()); + } + else + { + PushDescriport(vertexProp, vertexDescr, NNP_K1, &(*mesh.vert.begin()).K1()); + PushDescriport(vertexProp, vertexDescr, NNP_K2, &(*mesh.vert.begin()).K2()); + PushDescriportList(vertexProp, vertexDescr, NNP_K1DIR, (*mesh.vert.begin()).PD1().V()); + PushDescriportList(vertexProp, vertexDescr, NNP_K2DIR, (*mesh.vert.begin()).PD2().V()); + } + } + if ((bitMask & BitMask::IO_VERTATTRIB)) + { + std::set::iterator ai; + int userSize = custom.vertexAttrib.size(); + for (ai = mesh.vert_attr.begin(); ai != mesh.vert_attr.end(); ++ai) + { + bool userDescr = false; + for (int i = 0; i < userSize; i++) + { + if ((*custom.vertexAttrib[i]).name == (*ai)._name) + { + userDescr = true; + break; + } + } + if (!userDescr) + custom.CreateVertexAttribDescriptor(&(*ai)); + } + for (int i = 0; i < custom.vertexAttrib.size(); i++) + { + vertexProp.push_back(custom.vertexAttribProp[i]); + vertexDescr.dataDescriptor.push_back(custom.vertexAttrib[i]); + } } } @@ -606,14 +1443,31 @@ namespace nanoply PushDescriport(edgeProp, edgeDescr, NNP_CRGBA, (*mesh.edge.begin()).C().V()); if ((bitMask & BitMask::IO_EDGEFLAGS) && vcg::tri::HasPerEdgeFlags(mesh)) PushDescriport(edgeProp, edgeDescr, NNP_BITFLAG, &(*mesh.edge.begin()).Flags()); - if ((bitMask & BitMask::IO_EDGEATTRIB) && custom.edgeAttrib.size() > 0) - { - for (int i = 0; i < custom.edgeAttrib.size(); i++) - { - edgeProp.push_back(custom.edgeAttribProp[i]); - edgeDescr.dataDescriptor.push_back(custom.edgeAttrib[i]); - } - } + + if ((bitMask & BitMask::IO_EDGEATTRIB)) + { + std::set::iterator ai; + int userSize = custom.edgeAttrib.size(); + for (ai = mesh.edge_attr.begin(); ai != mesh.edge_attr.end(); ++ai) + { + bool userDescr = false; + for (int i = 0; i < userSize; i++) + { + if ((*custom.edgeAttrib[i]).name == (*ai)._name) + { + userDescr = true; + break; + } + } + if (!userDescr) + custom.CreateEdgeAttribDescriptor(&(*ai)); + } + for (int i = 0; i < custom.edgeAttrib.size(); i++) + { + edgeProp.push_back(custom.edgeAttribProp[i]); + edgeDescr.dataDescriptor.push_back(custom.edgeAttrib[i]); + } + } } //Face @@ -621,11 +1475,14 @@ namespace nanoply FaceType::Name(nameList); std::vector faceProp; ElementDescriptor faceDescr(NNP_FACE_ELEM); - std::vector faceIndex; + std::vector> faceIndex; std::vector> wedgeTexCoord; - for (int i = 0; i < mesh.face.size(); i++) - faceIndex.push_back(vcg::Point3i(vcg::tri::Index(mesh, mesh.face[i].V(0)), vcg::tri::Index(mesh, mesh.face[i].V(1)), vcg::tri::Index(mesh, mesh.face[i].V(2)))); - + for (int i = 0; i < mesh.face.size(); i++) + { + faceIndex.push_back(std::vector()); + for (int j = 0; j < mesh.face[i].VN(); j++) + faceIndex.back().push_back(vcg::tri::Index(mesh, mesh.face[i].V(j))); + } if (((bitMask & BitMask::IO_WEDGTEXCOORD) || (bitMask & BitMask::IO_WEDGTEXMULTI)) && vcg::tri::HasPerWedgeTexCoord(mesh)) { for (int i = 0; i < mesh.face.size(); i++) @@ -641,39 +1498,94 @@ namespace nanoply if (nameList.size() > 0 && mesh.face.size() > 0) { if ((bitMask & BitMask::IO_FACEINDEX) && FaceType::HasVertexRef()) - PushDescriportList(faceProp, faceDescr, NNP_FACE_VERTEX_LIST, (*faceIndex.begin()).V()); + PushDescriportList, unsigned int, 0>(faceProp, faceDescr, NNP_FACE_VERTEX_LIST, &faceIndex[0]); if ((bitMask & BitMask::IO_FACEFLAGS) && vcg::tri::HasPerFaceFlags(mesh)) PushDescriport(faceProp, faceDescr, NNP_BITFLAG, &(*mesh.face.begin()).Flags()); - if ((bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh)) - PushDescriport(faceProp, faceDescr, NNP_CRGBA, (*mesh.face.begin()).C().V()); - if ((bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh)) - PushDescriport(faceProp, faceDescr, NNP_QUALITY, &(*mesh.face.begin()).Q()); - if ((bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh)) - PushDescriport(faceProp, faceDescr, NNP_NXYZ, (*mesh.face.begin()).N().V()); + if ((bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh)) + { + if (ocfFaceMask & BitMask::IO_FACECOLOR) + PushDescriport(faceProp, faceDescr, NNP_CRGBA, (*mesh.face.begin()).C().V()); + else + PushDescriport(faceProp, faceDescr, NNP_CRGBA, (*mesh.face.begin()).C().V()); + } + if ((bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh)) + { + if (ocfFaceMask & BitMask::IO_FACEQUALITY) + PushDescriport(faceProp, faceDescr, NNP_QUALITY, &(*mesh.face.begin()).Q()); + else + PushDescriport(faceProp, faceDescr, NNP_QUALITY, &(*mesh.face.begin()).Q()); + } + if ((bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh)) + { + if (ocfFaceMask & BitMask::IO_FACENORMAL) + PushDescriport(faceProp, faceDescr, NNP_NXYZ, (*mesh.face.begin()).N().V()); + else + PushDescriport(faceProp, faceDescr, NNP_NXYZ, (*mesh.face.begin()).N().V()); + } if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerFaceCurvatureDir(mesh)) { - PushDescriport(faceProp, faceDescr, NNP_K1, &(*mesh.face.begin()).K1()); - PushDescriport(faceProp, faceDescr, NNP_K2, &(*mesh.face.begin()).K2()); - PushDescriportList(faceProp, faceDescr, NNP_K1DIR, (*mesh.face.begin()).PD1().V()); - PushDescriportList(faceProp, faceDescr, NNP_K2DIR, (*mesh.face.begin()).PD2().V()); + if (ocfFaceMask & BitMask::IO_VERTCURVDIR) + { + PushDescriport(faceProp, faceDescr, NNP_K1, &(*mesh.face.begin()).K1()); + PushDescriport(faceProp, faceDescr, NNP_K2, &(*mesh.face.begin()).K2()); + PushDescriportList(faceProp, faceDescr, NNP_K1DIR, (*mesh.face.begin()).PD1().V()); + PushDescriportList(faceProp, faceDescr, NNP_K2DIR, (*mesh.face.begin()).PD2().V()); + } + else + { + PushDescriport(faceProp, faceDescr, NNP_K1, &(*mesh.face.begin()).K1()); + PushDescriport(faceProp, faceDescr, NNP_K2, &(*mesh.face.begin()).K2()); + PushDescriportList(faceProp, faceDescr, NNP_K1DIR, (*mesh.face.begin()).PD1().V()); + PushDescriportList(faceProp, faceDescr, NNP_K2DIR, (*mesh.face.begin()).PD2().V()); + } } if (((bitMask & BitMask::IO_WEDGTEXCOORD) || (bitMask & BitMask::IO_WEDGTEXMULTI)) && vcg::tri::HasPerWedgeTexCoord(mesh)) PushDescriportList, FaceTexScalar, 6>(faceProp, faceDescr, NNP_FACE_WEDGE_TEX, (*wedgeTexCoord.begin()).V()); - if ((bitMask & BitMask::IO_WEDGTEXMULTI) && vcg::tri::HasPerWedgeTexCoord(mesh)) - PushDescriport(faceProp, faceDescr, NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N()); - if ((bitMask & BitMask::IO_WEDGCOLOR) && vcg::tri::HasPerWedgeColor(mesh)) - PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V()); - if ((bitMask & BitMask::IO_WEDGNORMAL) && vcg::tri::HasPerWedgeNormal(mesh)) - PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V()); - if ((bitMask & BitMask::IO_FACEATTRIB) && custom.faceAttrib.size() > 0) - { - for (int i = 0; i < custom.faceAttrib.size(); i++) - { - faceProp.push_back(custom.faceAttribProp[i]); - faceDescr.dataDescriptor.push_back(custom.faceAttrib[i]); - } - } - + if ((bitMask & BitMask::IO_WEDGTEXMULTI) && vcg::tri::HasPerWedgeTexCoord(mesh)) + { + if (ocfFaceMask & BitMask::IO_VERTCURVDIR) + PushDescriport(faceProp, faceDescr, NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N()); + else + PushDescriport(faceProp, faceDescr, NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N()); + } + if ((bitMask & BitMask::IO_WEDGCOLOR) && vcg::tri::HasPerWedgeColor(mesh)) + { + if (ocfFaceMask & BitMask::IO_WEDGCOLOR) + PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V()); + else + PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V()); + } + if ((bitMask & BitMask::IO_WEDGNORMAL) && vcg::tri::HasPerWedgeNormal(mesh)) + { + if (ocfFaceMask & BitMask::IO_WEDGNORMAL) + PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V()); + else + PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V()); + } + if ((bitMask & BitMask::IO_FACEATTRIB)) + { + std::set::iterator ai; + int userSize = custom.faceAttrib.size(); + for (ai = mesh.face_attr.begin(); ai != mesh.face_attr.end(); ++ai) + { + bool userDescr = false; + for (int i = 0; i < userSize; i++) + { + if ((*custom.faceAttrib[i]).name == (*ai)._name) + { + userDescr = true; + break; + } + } + if (!userDescr) + custom.CreateFaceAttribDescriptor(&(*ai)); + } + for (int i = 0; i < custom.faceAttrib.size(); i++) + { + faceProp.push_back(custom.faceAttribProp[i]); + faceDescr.dataDescriptor.push_back(custom.faceAttrib[i]); + } + } } Info infoSave; diff --git a/wrap/qt/shot_qt.h b/wrap/qt/shot_qt.h index 6ac49c81..e2dc32e4 100644 --- a/wrap/qt/shot_qt.h +++ b/wrap/qt/shot_qt.h @@ -16,31 +16,55 @@ template if(QString::compare(node.nodeName(),"VCGCamera")==0) { QDomNamedNodeMap attr = node.attributes(); - Point3x tra; - tra[0] = attr.namedItem("TranslationVector").nodeValue().section(' ',0,0).toDouble(); - tra[1] = attr.namedItem("TranslationVector").nodeValue().section(' ',1,1).toDouble(); - tra[2] = attr.namedItem("TranslationVector").nodeValue().section(' ',2,2).toDouble(); - shot.Extrinsics.SetTra(-tra); + if (attr.contains("BinaryData") && attr.namedItem("BinaryData").nodeValue().toInt() == 1) + { + Point3x tra; + QString str = attr.namedItem("TranslationVector").nodeValue(); + QByteArray value = QByteArray::fromBase64(str.toLocal8Bit()); + memcpy(tra.V(), value.data(), sizeof(ScalarType) * 3); + shot.Extrinsics.SetTra(-tra); - vcg::Matrix44 rot; - QStringList values = attr.namedItem("RotationMatrix").nodeValue().split(" ", QString::SkipEmptyParts); - for(int y = 0; y < 4; y++) - for(int x = 0; x < 4; x++) - rot[y][x] = values[x + 4*y].toDouble(); - shot.Extrinsics.SetRot(rot); + vcg::Matrix44 rot; + str = attr.namedItem("RotationMatrix").nodeValue(); + value = QByteArray::fromBase64(str.toLocal8Bit()); + memcpy(rot.V(), value.data(), sizeof(ScalarType) * 16); + shot.Extrinsics.SetRot(rot); - vcg::Camera &cam = shot.Intrinsics; - if(attr.contains("CameraType")) cam.cameraType = attr.namedItem("CameraType").nodeValue().toInt(); - cam.FocalMm = attr.namedItem("FocalMm").nodeValue().toDouble(); - cam.ViewportPx.X() = attr.namedItem("ViewportPx").nodeValue().section(' ',0,0).toInt(); - cam.ViewportPx.Y() = attr.namedItem("ViewportPx").nodeValue().section(' ',1,1).toInt(); - cam.CenterPx[0] = attr.namedItem("CenterPx").nodeValue().section(' ', 0, 0).toDouble(); - cam.CenterPx[1] = attr.namedItem("CenterPx").nodeValue().section(' ', 1, 1).toDouble(); - cam.PixelSizeMm[0] = attr.namedItem("PixelSizeMm").nodeValue().section(' ',0,0).toDouble(); - cam.PixelSizeMm[1] = attr.namedItem("PixelSizeMm").nodeValue().section(' ',1,1).toDouble(); - cam.k[0] = attr.namedItem("LensDistortion").nodeValue().section(' ',0,0).toDouble(); - cam.k[1] = attr.namedItem("LensDistortion").nodeValue().section(' ',1,1).toDouble(); + vcg::Camera &cam = shot.Intrinsics; + if (attr.contains("CameraType")) cam.cameraType = attr.namedItem("CameraType").nodeValue().toInt(); + memcpy(&cam.FocalMm, QByteArray::fromBase64(attr.namedItem("FocalMm").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType)); + memcpy(&cam.ViewportPx, QByteArray::fromBase64(attr.namedItem("ViewportPx").nodeValue().toLocal8Bit()).data(), sizeof(int) * 2); + memcpy(&cam.CenterPx, QByteArray::fromBase64(attr.namedItem("CenterPx").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType)*2); + memcpy(&cam.PixelSizeMm, QByteArray::fromBase64(attr.namedItem("PixelSizeMm").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType) * 2); + memcpy(&cam.k, QByteArray::fromBase64(attr.namedItem("LensDistortion").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType) * 2); + } + else + { + Point3x tra; + tra[0] = attr.namedItem("TranslationVector").nodeValue().section(' ', 0, 0).toDouble(); + tra[1] = attr.namedItem("TranslationVector").nodeValue().section(' ', 1, 1).toDouble(); + tra[2] = attr.namedItem("TranslationVector").nodeValue().section(' ', 2, 2).toDouble(); + shot.Extrinsics.SetTra(-tra); + vcg::Matrix44 rot; + QStringList values = attr.namedItem("RotationMatrix").nodeValue().split(" ", QString::SkipEmptyParts); + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + rot[y][x] = values[x + 4 * y].toDouble(); + shot.Extrinsics.SetRot(rot); + + vcg::Camera &cam = shot.Intrinsics; + if (attr.contains("CameraType")) cam.cameraType = attr.namedItem("CameraType").nodeValue().toInt(); + cam.FocalMm = attr.namedItem("FocalMm").nodeValue().toDouble(); + cam.ViewportPx.X() = attr.namedItem("ViewportPx").nodeValue().section(' ', 0, 0).toInt(); + cam.ViewportPx.Y() = attr.namedItem("ViewportPx").nodeValue().section(' ', 1, 1).toInt(); + cam.CenterPx[0] = attr.namedItem("CenterPx").nodeValue().section(' ', 0, 0).toDouble(); + cam.CenterPx[1] = attr.namedItem("CenterPx").nodeValue().section(' ', 1, 1).toDouble(); + cam.PixelSizeMm[0] = attr.namedItem("PixelSizeMm").nodeValue().section(' ', 0, 0).toDouble(); + cam.PixelSizeMm[1] = attr.namedItem("PixelSizeMm").nodeValue().section(' ', 1, 1).toDouble(); + cam.k[0] = attr.namedItem("LensDistortion").nodeValue().section(' ', 0, 0).toDouble(); + cam.k[1] = attr.namedItem("LensDistortion").nodeValue().section(' ', 1, 1).toDouble(); + } // scale correction should no more exist !!! // float scorr = attr.namedItem("ScaleCorr").nodeValue().toDouble(); // if(scorr != 0.0) { @@ -120,6 +144,7 @@ template const vcg::Camera &cam = shot.Intrinsics; shotElem.setAttribute("CameraType", cam.cameraType); + shotElem.setAttribute("BinaryData", 0); shotElem.setAttribute( "FocalMm", cam.FocalMm); @@ -142,4 +167,50 @@ template } +template +QDomElement WriteShotToQDomNodeBinary( + const ShotType &shot, /// the shot to be written node + QDomDocument &doc) /// The XML node to be read +{ + typedef typename ShotType::ScalarType ScalarType; + + QDomElement shotElem = doc.createElement("VCGCamera"); + vcg::Point3 tra = -(shot.Extrinsics.Tra()); + + QByteArray value = QByteArray::fromRawData((char *)tra.V(), sizeof(ScalarType) * 3).toBase64(); + shotElem.setAttribute("TranslationVector", QString(value)); + + vcg::Matrix44 rot = shot.Extrinsics.Rot(); + value = QByteArray::fromRawData((char *)rot.V(), sizeof(ScalarType) * 16).toBase64(); + shotElem.setAttribute("RotationMatrix", QString(value)); + + const vcg::Camera &cam = shot.Intrinsics; + + shotElem.setAttribute("CameraType", cam.cameraType); + + shotElem.setAttribute("BinaryData", 1); + + value = QByteArray::fromRawData((char *)&cam.FocalMm, sizeof(ScalarType)).toBase64(); + shotElem.setAttribute("FocalMm", QString(value)); + + value = QByteArray::fromRawData((char *)&cam.k, sizeof(ScalarType) * 2).toBase64(); + shotElem.setAttribute("LensDistortion", QString(value)); + + value = QByteArray::fromRawData((char *)&cam.PixelSizeMm, sizeof(ScalarType) * 2).toBase64(); + shotElem.setAttribute("PixelSizeMm", QString(value)); + + value = QByteArray::fromRawData((char *)&cam.ViewportPx, sizeof(int) * 2).toBase64(); + shotElem.setAttribute("ViewportPx", QString(value)); + + //str = QString("%1 %2").arg(cam.CenterPx[0]).arg(cam.CenterPx[1]); + value = QByteArray::fromRawData((char *)&cam.CenterPx, sizeof(ScalarType) * 2).toBase64(); + shotElem.setAttribute("CenterPx", QString(value)); + + //scale correction should no more exist !!! + //str = QString("%1").arg((double) 1); + //shotElem.setAttribute( "ScaleCorr", str); + return shotElem; +} + + #endif // SHOT_QT_H