From b91d8334d5c84ed4d61316567dff0af6072061a5 Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 8 Mar 2004 09:24:59 +0000 Subject: [PATCH] Initial commit --- docs/Doxygen/groups.dxy | 2 +- docs/Doxygen/namespaces.dxy | 1 + vcg/space/index/ugrid.h | 655 +++++++++++++++++++++++++++++++++++ wrap/io_trimesh/export_ply.h | 564 ++++++++++++++++++++++++++++++ wrap/io_trimesh/io_ply.h | 104 ++++++ 5 files changed, 1325 insertions(+), 1 deletion(-) create mode 100644 docs/Doxygen/namespaces.dxy create mode 100644 vcg/space/index/ugrid.h create mode 100644 wrap/io_trimesh/export_ply.h create mode 100644 wrap/io_trimesh/io_ply.h diff --git a/docs/Doxygen/groups.dxy b/docs/Doxygen/groups.dxy index 53fd4f2a..8cd0fb86 100644 --- a/docs/Doxygen/groups.dxy +++ b/docs/Doxygen/groups.dxy @@ -7,4 +7,4 @@ This module contains the documentation for the type and the functions used for r /** \defgroup face Faces */ /** \defgroup trimesh Triangular Meshes -*/ +*/ \ No newline at end of file diff --git a/docs/Doxygen/namespaces.dxy b/docs/Doxygen/namespaces.dxy new file mode 100644 index 00000000..d1a6566d --- /dev/null +++ b/docs/Doxygen/namespaces.dxy @@ -0,0 +1 @@ + /** Main namespace */ namespace vcg {} /** Everything about meshes lie in this namespace */ namespace vcg::tri {} /** Wrapper for symbols and structs defind in the old ply library */ namespace vcg::ply {} /** For all the functions and classes used to read and write meshes */ namespace vcg::tri::io {} \ No newline at end of file diff --git a/vcg/space/index/ugrid.h b/vcg/space/index/ugrid.h new file mode 100644 index 00000000..10ee97a9 --- /dev/null +++ b/vcg/space/index/ugrid.h @@ -0,0 +1,655 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + +$Log: not supported by cvs2svn $ +****************************************************************************/ + +#ifndef __VCGLIB_UGRID +#define __VCGLIB_UGRID + +namespace vcg { + + /** Static Uniform Grid + A spatial search structure for a accessing a container of objects. It is based on a uniform grid overlayed over a protion of space. + The grid partion the space into cells. Cells contains just pointers to the object that are stored elsewhere. + The set of object is meant to be static and pointer stable. + Useful for situation were many space related query are issued over the same dataset (ray tracing, measuring distances between meshes, re-detailing ecc.). Works well for distribution that ar reasonably uniform. + How to use it: + + */ +template < class ContainerType > +class UGrid +{ +public: + + /** Internal class for keeping the first pointer of object. + Definizione Link dentro la griglia. Classe di supporto per UGrid. + */ + class Link + { + public: + /// Costruttore di default + inline Link(){}; + /// Costruttore con inizializzatori + inline Link( ContainerType::iterator const nt, const int ni ){ + assert(ni>=0); + t = nt; + i = ni; + }; + + + inline bool operator < ( const Link & l ) const{ return i < l.i; } + inline bool operator <= ( const Link & l ) const{ return i <= l.i; } + inline bool operator > ( const Link & l ) const{ return i > l.i; } + inline bool operator >= ( const Link & l ) const{ return i >= l.i; } + inline bool operator == ( const Link & l ) const{ return i == l.i; } + inline bool operator != ( const Link & l ) const{ return i != l.i; } + + inline ContainerType::iterator & Elem() { + return t; + } + inline int & Index() { + return i; + } + + private: + /// Puntatore all'elemento T + ContainerType::iterator t; + /// Indirizzo del voxel dentro la griglia + int i; + + + };//end class Link + + typedef ContainerType::value_type ObjType; + typedef ObjType::ScalarType ScalarType; + typedef Point3 Point3x; + typedef Box3 Box3x; + typedef Line3 Line3x; + + Box3x bbox; + Point3x dim; /// Dimensione spaziale (lunghezza lati) del bbox + Point3i siz; /// Dimensioni griglia in celle + Point3x voxel; /// Dimensioni di una cella + + /// Insieme di tutti i links + vector links; + /// Griglia vera e propria + vector grid; + + /// Dato un punto, ritorna la cella che lo contiene + inline Link ** Grid( const Point3d & p ) + { + int x = int( (p[0]-bbox.min[0])/voxel[0] ); + int y = int( (p[1]-bbox.min[1])/voxel[1] ); + int z = int( (p[2]-bbox.min[2])/voxel[2] ); + +#ifndef NDEBUG + if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] ) + return NULL; + else +#endif + + return grid.begin() + ( x+siz[0]*(y+siz[1]*z) ); + } + /// Date le coordinate ritorna la cella + inline Link ** Grid( const int x, const int y, const int z ) + { +#ifndef NDEBUG + if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] ) + assert(0); + //return NULL; + else +#endif + assert(x+siz[0]*(y+siz[1]*z0) { + printf("\n%d rays (%f faces in %f voxel per ray)\n", + n_rays, + double(n_traversed_elem)/n_rays, + double(n_traversed_voxel)/n_rays); + printf("HIT: %d rays (%d%%) (%f faces in %f voxel per ray)\n", + n_rays_hit, + (n_rays_hit*100)/n_rays, + double(n_traversed_elem_hit)/n_rays_hit, + double(n_traversed_voxel_hit)/n_rays_hit); + } + } +#endif + + void ShowStats(FILE *fp) + { + // Conto le entry + int nentry = 0; + Hist H; + H.SetRange(0,1000,1000); + int pg; + for(pg=0;pg0.5) radius=(1.0-radius); radius*=voxel[0]; + + /*ScalarType radio_if[6]; + radio_if[0]= (dx-double(ix) )*voxel[0] ; + radio_if[1]= (dy-double(iy) )*voxel[1] ; + radio_if[2]= (dz-double(iz) )*voxel[2] ; + radio_if[3]= (1.0+double(ix)-dx)*voxel[0] ; + radio_if[4]= (1.0+double(iy)-dy)*voxel[1] ; + radio_if[5]= (1.0+double(iz)-dz)*voxel[2] ;*/ + + ScalarType + tmp=dy-ScalarType(iy); if (tmp>0.5) tmp=1.0-tmp; tmp*=voxel[1]; if (radius>tmp) radius=tmp; + tmp=dz-ScalarType(iz); if (tmp>0.5) tmp=1.0-tmp; tmp*=voxel[2]; if (radius>tmp) radius=tmp; + + Point3x t_res; + //ScalarType min_dist=1e10; + T* winner=NULL; + + Link *first, *last, *l; + if ((ix>=0) && (iy>=0) && (iz>=0) && (ixElem()->Dist(p,min_dist,t_res)) { + winner=&*(l->Elem()); + res=t_res; + + } + }; + }; + + //return winner; + + Point3i done_min=Point3i(ix,iy,iz), done_max=Point3i(ix,iy,iz); + + //printf("."); + + while (min_dist>radius) { + //if (dy-ScalarType(iy)) + done_min[0]--; if (done_min[0]<0) done_min[0]=0; + done_min[1]--; if (done_min[1]<0) done_min[1]=0; + done_min[2]--; if (done_min[2]<0) done_min[2]=0; + done_max[0]++; if (done_max[0]>=siz[0]-1) done_max[0]=siz[0]-1; + done_max[1]++; if (done_max[1]>=siz[1]-1) done_max[1]=siz[1]-1; + done_max[2]++; if (done_max[2]>=siz[2]-1) done_max[2]=siz[2]-1; + radius+=voxel_min; + //printf("+"); + for (ix=done_min[0]; ix<=done_max[0]; ix++) + for (iy=done_min[1]; iy<=done_max[1]; iy++) + for (iz=done_min[2]; iz<=done_max[2]; iz++) + { + Grid( ix, iy, iz, first, last ); + for(l=first;l!=last;++l) + { + if (l->Elem()->Dist(p,min_dist,t_res)) { + winner=&*(l->Elem()); + res=t_res; + }; + }; + } + }; + return winner; + }; + + T * DoRay( Line3x & ray, double & dist , double &p_a, double &p_b) + { + int ix,iy,iz; + double gx,gy,gz; + + if(!bbox.IsIn(ray.orig)) + { + //printf("."); + + Point3x ip; + if(Intersection(bbox,ray,ip)) + { + ix = int( (ip.x() - bbox.min.x())/voxel.x() ); + iy = int( (ip.y() - bbox.min.y())/voxel.y() ); + iz = int( (ip.z() - bbox.min.z())/voxel.z() ); + if(ix<0) ix = 0; + if(iy<0) iy = 0; + if(iz<0) iz = 0; + if(ix>=siz[0]) ix = siz[0]-1; + if(iy>=siz[1]) iy = siz[1]-1; + if(iz>=siz[2]) iz = siz[2]-1; + } + else + return 0; + } + else + { + /* Indici di voxel */ + ix = int( (ray.orig.x() - bbox.min.x())/voxel.x() ); + iy = int( (ray.orig.y() - bbox.min.y())/voxel.y() ); + iz = int( (ray.orig.z() - bbox.min.z())/voxel.z() ); + } + + /* Punti goal */ + if(ray.dire.x()>0.0) gx=double(ix+1)*voxel.x()+bbox.min.x(); + else gx=double(ix )*voxel.x()+bbox.min.x(); + if(ray.dire.y()>0.0) gy=double(iy+1)*voxel.y()+bbox.min.y(); + else gy=double(iy )*voxel.y()+bbox.min.y(); + if(ray.dire.z()>0.0) gz=double(iz+1)*voxel.z()+bbox.min.z(); + else gz=double( iz )*voxel.z()+bbox.min.z(); + + const ScalarType MAXFLOAT = 1e50; + const ScalarType EPSILON = 1e-50; + + /* Parametri della linea */ + double tx,ty,tz; + if( fabs(ray.dire.x())>EPSILON ) tx = (gx-ray.orig.x())/ray.dire.x(); + else tx = MAXFLOAT; + if( fabs(ray.dire.y())>EPSILON ) ty = (gy-ray.orig.y())/ray.dire.y(); + else ty = MAXFLOAT; + if( fabs(ray.dire.z())>EPSILON ) tz = (gz-ray.orig.z())/ray.dire.z(); + else tz = MAXFLOAT; + + T * bestf = NULL; + +#ifdef MONITOR_GRID + int n_traversed_voxel0=0,n_traversed_elem0=0; + n_rays++; +#endif + for(;;) + { + Link *first, *last, *l; + Grid( ix, iy, iz, first, last ); +#ifdef MONITOR_GRID + n_traversed_voxel++;n_traversed_voxel0++; +#endif + for(l=first;l!=last;++l) + { +#ifdef MONITOR_GRID + n_traversed_elem++;n_traversed_elem0++; +#endif + //return &(*(l->Elem())); + if(l->Elem()->Intersect(ray,dist, p_a, p_b)) { +#ifdef MONITOR_GRID + n_traversed_voxel_hit+=n_traversed_voxel0; + n_traversed_elem_hit+=n_traversed_elem0; + n_rays_hit++; +#endif + + return &(*(l->Elem())); + //{ + // bestf = &(*(l->Elem())); break; + //} + } + //if(bestf) break; + } + + if( tx=siz[0]) break; } + tx = (gx-ray.orig.x())/ray.dire.x(); + } else if( ty=siz[1]) break; } + ty = (gy-ray.orig.y())/ray.dire.y(); + } else { + if(ray.dire.z()<0.0) { gz -= voxel.z(); --iz; if(iz<0 ) break; } + else { gz += voxel.z(); ++iz; if(iz>=siz[2]) break; } + tz = (gz-ray.orig.z())/ray.dire.z(); + } + } + return bestf; + } + + + /// Inserisce una mesh nella griglia. Nota: prima bisogna + /// chiamare SetBBox che setta dim in maniera corretta + void Set( S & s ) + { + Set(s,s.size()); + } + + + /// Inserisce una mesh nella griglia. Nota: prima bisogna + /// chiamare SetBBox che setta dim in maniera corretta + void Set( S & s,int _size ) + { + Point3i _siz; + + BestDim( _size, dim, _siz ); + Set(s,_siz); + } + void Set(S & s, Point3i _siz) + { + siz=_siz; + // Calcola la dimensione della griglia + voxel[0] = dim[0]/siz[0]; + voxel[1] = dim[1]/siz[1]; + voxel[2] = dim[2]/siz[2]; + + // "Alloca" la griglia: +1 per la sentinella + grid.resize( siz[0]*siz[1]*siz[2]+1 ); + + // Ciclo inserimento dei tetraedri: creazione link + links.clear(); + S::iterator pt; + for(pt=s.begin(); pt!=s.end(); ++pt) + { + Box3x bb; // Boundig box del tetraedro corrente + (*pt).GetBBox(bb); + bb.Intersect(bbox); + if(! bb.IsNull() ) + { + Box3i ib; // Boundig box in voxels + BoxToIBox( bb,ib ); + /*ib.min-=Point3i(1,1,1); + ib.max+=Point3i(1,1,1); + if (ib.min[0]<0) ib.min[0]=0; + if (ib.min[1]<0) ib.min[1]=0; + if (ib.min[2]<0) ib.min[2]=0; + if (ib.max[0]>siz[0]) ib.max[0]=siz[0]; + if (ib.max[1]>siz[1]) ib.max[1]=siz[1]; + if (ib.max[2]>siz[2]) ib.max[2]=siz[2];*/ + + int x,y,z; + for(z=ib.min[2];z<=ib.max[2];++z) + { + int bz = z*siz[1]; + for(y=ib.min[1];y<=ib.max[1];++y) + { + int by = (y+bz)*siz[0]; + for(x=ib.min[0];x<=ib.max[0];++x) + // Inserire calcolo cella corrente + // if( pt->Intersect( ... ) + links.push_back( Link(pt,by+x) ); + } + } + } + } + // Push della sentinella + links.push_back( Link(NULL,grid.size()-1) ); + + // Ordinamento dei links + sort( links.begin(), links.end() ); + + // Creazione puntatori ai links + vector::iterator pl; + int pg; + pl = links.begin(); + for(pg=0;pgIndex() ) // Trovato inizio + { + ++pl; // Ricerca prossimo blocco + if(pl==links.end()) + break; + } + } + + } + + /** Calcolo dimensioni griglia. + Calcola la dimensione della griglia in funzione + della ratio del bounding box e del numero di elementi + */ + static void BestDim( const int elems, const Point3x & size, Point3i & dim ) + { + const int mincells = 27; // Numero minimo di celle + const double GFactor = 1.0; // GridEntry = NumElem*GFactor + double diag = size.Norm(); // Diagonale del box + double eps = diag*1e-4; // Fattore di tolleranza + + assert(elems>0); + assert(size[0]>=0.0); + assert(size[1]>=0.0); + assert(size[2]>=0.0); + + int ncell = int(elems*GFactor); // Calcolo numero di voxel + if(ncelleps) + { + if(size[1]>eps) + { + if(size[2]>eps) + { + double k = pow(ncell/(size[0]*size[1]*size[2]),1.0/3.0); + dim[0] = int(size[0] * k); + dim[1] = int(size[1] * k); + dim[2] = int(size[2] * k); + } + else + { + dim[0] = int(::sqrt(ncell*size[0]/size[1])); + dim[1] = int(::sqrt(ncell*size[1]/size[0])); + } + } + else + { + if(size[2]>eps) + { + dim[0] = int(::sqrt(ncell*size[0]/size[2])); + dim[2] = int(::sqrt(ncell*size[2]/size[0])); + } + else + dim[0] = int(ncell); + } + } + else + { + if(size[1]>eps) + { + if(size[2]>eps) + { + dim[1] = int(::sqrt(ncell*size[1]/size[2])); + dim[2] = int(::sqrt(ncell*size[2]/size[1])); + } + else + dim[1] = int(ncell); + } + else if(size[2]>eps) + dim[2] = int(ncell); + } + } + + + int MemUsed() + { + return sizeof(UGrid)+ sizeof(Link)*links.size() + sizeof(Link *) * grid.size(); + } +}; //end class UGrid + +} // end namespace + +#endif diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h new file mode 100644 index 00000000..7f06a84a --- /dev/null +++ b/wrap/io_trimesh/export_ply.h @@ -0,0 +1,564 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + +$Log: not supported by cvs2svn $ +Revision 1.1 2004/03/03 15:00:51 cignoni +Initial commit + +****************************************************************************/ + +/** +@name Load and Save in Ply format +*/ +//@{ + +#ifndef __VCGLIB_EXPORT_PLY +#define __VCGLIB_EXPORT_PLY + +#include +#include + +#include + +namespace vcg { +namespace tri { +namespace io { + + +template +class ExporterPLY +{ +public: +typedef ::vcg::ply::PropDescriptor PropDescriptor ; +typedef typename SaveMeshType::VertexPointer VertexPointer; +typedef typename SaveMeshType::ScalarType ScalarType; +typedef typename SaveMeshType::VertexType VertexType; +typedef typename SaveMeshType::FaceType FaceType; +typedef typename SaveMeshType::VertexIterator VertexIterator; +typedef typename SaveMeshType::FaceIterator FaceIterator; + +static bool Save(SaveMeshType &m, const char * filename, bool binary=true) +{ + PlyInfo pi; + return SavePly(m,filename,binary,pi); +} + +static bool SavePly(SaveMeshType &m, const char * filename, int savemask ) +{ + PlyInfo pi; + pi.mask=savemask; + return SavePly(m,filename,true,pi); +} + +static bool SavePly(SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi ) // V1.0 +{ + FILE * fpout; + int i; + + const char * hbin = "binary_little_endian"; + const char * hasc = "ascii"; + const char * h; + + bool multit = false; + + if(binary) h=hbin; + else h=hasc; + + fpout = fopen(filename,"wb"); + if(fpout==NULL) { + pi.status=::vcg::ply::E_CANTOPEN; + return false; + } + fprintf(fpout, + "ply\n" + "format %s 1.0\n" + "comment VCGLIB generated\n" + ,h + ); + + if( pi.mask & PLYMask::PM_WEDGTEXCOORD ) + { + //const char * TFILE = "TextureFile"; + + //for(i=0;i1 && (HasPerWedgeTexture() || HasPerVertexTexture())) multit = true; + } + + //if( (pi.mask & PLYMask::PM_CAMERA) && camera.IsValid() ) + /*{ + fprintf(fpout, + "element camera 1\n" + "property float view_px\n" + "property float view_py\n" + "property float view_pz\n" + "property float x_axisx\n" + "property float x_axisy\n" + "property float x_axisz\n" + "property float y_axisx\n" + "property float y_axisy\n" + "property float y_axisz\n" + "property float z_axisx\n" + "property float z_axisy\n" + "property float z_axisz\n" + "property float focal\n" + "property float scalex\n" + "property float scaley\n" + "property float centerx\n" + "property float centery\n" + "property int viewportx\n" + "property int viewporty\n" + "property float k1\n" + "property float k2\n" + "property float k3\n" + "property float k4\n" + ); + }*/ + + fprintf(fpout, + "element vertex %d\n" + "property float x\n" + "property float y\n" + "property float z\n" + ,m.vn + ); + + + if( pi.mask & PLYMask::PM_VERTFLAGS ) + { + fprintf(fpout, + "property int flags\n" + ); + } + + if( HasPerVertexColor() && (pi.mask & PLYMask::PM_VERTCOLOR) ) + { + fprintf(fpout, + "property uchar red\n" + "property uchar green\n" + "property uchar blue\n" + "property uchar alpha\n" + ); + } + + if( HasPerVertexQuality() && (pi.mask & PLYMask::PM_VERTQUALITY) ) + { + fprintf(fpout, + "property float quality\n" + ); + } + + for(i=0;i FlagV; + MVTYPE * vp; + vertex_iterator vi; + for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi) + { + vp=&(*vi); + FlagV.push_back(vp->Supervisor_Flags()); // Salva in ogni caso flag del vertice + if( ! vp->IsDeleted() ) + { + if(binary) + { + float t; + + t = float(vp->Supervisor_P()[0]); fwrite(&t,sizeof(float),1,fpout); + t = float(vp->Supervisor_P()[1]); fwrite(&t,sizeof(float),1,fpout); + t = float(vp->Supervisor_P()[2]); fwrite(&t,sizeof(float),1,fpout); + + if( pi.mask & PLYMask::PM_VERTFLAGS ) + fwrite(&(vp->Supervisor_Flags()),sizeof(int),1,fpout); + + if( HasPerVertexColor() && (pi.mask & PLYMask::PM_VERTCOLOR) ) + fwrite(&( vp->C() ),sizeof(char),4,fpout); + + if( HasPerVertexQuality() && (pi.mask & PLYMask::PM_VERTQUALITY) ) + fwrite(&( vp->Q() ),sizeof(float),1,fpout); + + + for(i=0;iP()[0],vp->P()[1],vp->P()[2]); + + if( pi.mask & PLYMask::PM_VERTFLAGS ) + fprintf(fpout,"%d ",vp->Supervisor_Flags()); + + if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_C) && (pi.mask & PLYMask::PM_VERTCOLOR) ) + fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); + + if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_Q) && (pi.mask & PLYMask::PM_VERTQUALITY) ) + fprintf(fpout,"%g ",vp->Q()); + + for(i=0;iSupervisor_Flags()=j; // Trucco! Nascondi nei flags l'indice del vertice non deletato! + j++; + } + } + assert(j==vn); + + char c = 3; + char k = 9; + unsigned char b9 = 9; + unsigned char b6 = 6; + const MFTYPE * fp; + int vv[3]; + face_iterator fi; + int fcnt=0; + for(j=0,fi=face.begin();fi!=face.end();++fi) + { + fp=&(*fi); + if( ! fp->IsDeleted() ) + { fcnt++; + if(binary) + { + vv[0]=fp->cV(0)->Supervisor_Flags(); + vv[1]=fp->cV(1)->Supervisor_Flags(); + vv[2]=fp->cV(2)->Supervisor_Flags(); + fwrite(&c,1,1,fpout); + fwrite(vv,sizeof(int),3,fpout); + + if( pi.mask & PLYMask::PM_FACEFLAGS ) + fwrite(&(fp->Flags()),sizeof(int),1,fpout); + + if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_T) && (pi.mask & PLYMask::PM_VERTTEXCOORD) ) + { + fwrite(&b6,sizeof(char),1,fpout); + float t[6]; + for(int k=0;k<3;++k) + { + t[k*2+0] = fp->V(k)->T().u(); + t[k*2+1] = fp->V(k)->T().v(); + } + fwrite(t,sizeof(float),6,fpout); + } + else if( (face_type:: OBJ_TYPE & face_type:: OBJ_TYPE_WT) && (pi.mask & PLYMask::PM_WEDGTEXCOORD) ) + { + fwrite(&b6,sizeof(char),1,fpout); + float t[6]; + for(int k=0;k<3;++k) + { + t[k*2+0] = fp->WT(k).u(); + t[k*2+1] = fp->WT(k).v(); + } + fwrite(t,sizeof(float),6,fpout); + } + + if(multit) + { + int t = fp->WT(0).n(); + fwrite(&t,sizeof(int),1,fpout); + } + + if( HasPerFaceColor() && (pi.mask & PLYMask::PM_FACECOLOR) ) + fwrite(&( fp->C() ),sizeof(char),4,fpout); + + + if( HasPerWedgeColor() && (pi.mask & PLYMask::PM_WEDGCOLOR) ) + { + fwrite(&b9,sizeof(char),1,fpout); + float t[3]; + for(int z=0;z<3;++z) + { + t[0] = float(fp->WC(z)[0])/255; + t[1] = float(fp->WC(z)[1])/255; + t[2] = float(fp->WC(z)[2])/255; + fwrite( t,sizeof(float),3,fpout); + } + } + + if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_Q) && (pi.mask & PLYMask::PM_FACEQUALITY) ) + fwrite( &(fp->Q()),sizeof(float),1,fpout); + + + for(i=0;icV(0)->Supervisor_Flags(), fp->cV(1)->Supervisor_Flags(), fp->cV(2)->Supervisor_Flags() ); + + if( pi.mask & PLYMask::PM_FACEFLAGS ) + fprintf(fpout,"%d ",fp->Flags()); + + if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_T) && (pi.mask & PLYMask::PM_VERTTEXCOORD) ) + { + fprintf(fpout,"6 "); + for(int k=0;k<3;++k) + fprintf(fpout,"%g %g " + ,fp->V(k)->T().u() + ,fp->V(k)->T().v() + ); + } + else if( (face_type:: OBJ_TYPE & face_type:: OBJ_TYPE_WT) && (pi.mask & PLYMask::PM_WEDGTEXCOORD) ) + { + fprintf(fpout,"6 "); + for(int k=0;k<3;++k) + fprintf(fpout,"%g %g " + ,fp->WT(k).u() + ,fp->WT(k).v() + ); + } + + if(multit) + { + fprintf(fpout,"%d ",fp->WT(0).n()); + } + + if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_C) && (pi.mask & PLYMask::PM_FACECOLOR) ) + { + float t[3]; + t[0] = float(fp->C()[0])/255; + t[1] = float(fp->C()[1])/255; + t[2] = float(fp->C()[2])/255; + fprintf(fpout,"9 "); + fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); + fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); + fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); + } + else if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_WC) && (pi.mask & PLYMask::PM_WEDGCOLOR) ) + { + fprintf(fpout,"9 "); + for(int z=0;z<3;++z) + fprintf(fpout,"%g %g %g " + ,double(fp->WC(z)[0])/255 + ,double(fp->WC(z)[1])/255 + ,double(fp->WC(z)[2])/255 + ); + } + + if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_Q) && (pi.mask & PLYMask::PM_FACEQUALITY) ) + fprintf(fpout,"%g ",fp->Q()); + + for(i=0;i +#include + +namespace vcg { +namespace tri { +namespace io { + + +/** Additional data needed or useful for parsing a ply mesh. +This class can be passed to the ImporterPLY::Open() function for +- retrieving additional per-vertex per-face data +- specifying a callback for long ply parsing +- knowing what data is contained in a ply file +*/ +class PlyInfo +{ +public: + typedef ::vcg::ply::PropDescriptor PropDescriptor ; + + PlyInfo() + { + status=0; + mask=0; + cb=0; + vdn=fdn=0; + VertexData=FaceData=0; + } + /// Store the error codes enconutered when parsing a ply + int status; + /// It returns a bit mask describing the field preesnt in the ply file + int mask; + + /// a Simple callback that can be used for long ply parsing. + // it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...) + CallBackPos *cb; + + /// the number of per-vertex descriptor (usually 0) + int vdn; + /// The additional vertex descriptor that a user can specify to load additional per-vertex non-standard data stored in a ply + PropDescriptor *VertexData; + /// the number of per-face descriptor (usually 0) + int fdn; + + /// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply + PropDescriptor *FaceData; + + /// a string containing the current ply header. Useful for showing it to the user. + std::string header; + +enum Error +{ + // Funzioni superiori + E_NO_VERTEX, // 14 + E_NO_FACE, // 15 + E_SHORTFILE, // 16 + E_NO_3VERTINFACE, // 17 + E_BAD_VERT_INDEX, // 18 + E_NO_6TCOORD, // 19 + E_DIFFER_COLORS, // 20 +}; + +}; // end class +} // end namespace tri +} // end namespace io +} // end namespace vcg +#endif \ No newline at end of file