/**************************************************************************** * 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.10 2004/10/07 14:51:10 ganovelli added setidentity della camera Revision 1.9 2004/10/07 14:19:06 ganovelli shot/camera io added Revision 1.8 2004/06/23 15:36:43 cignoni Restructured management of error, now the standard open for any mesh type return the error code, the default success value is zero Any import class has a method ErrorMsg that give a verbal description of an error code. Revision 1.7 2004/06/11 17:09:41 ganovelli inclusion of vector..minorchanges Revision 1.6 2004/05/28 14:11:13 ganovelli changes to comply io_mask moving in vcg::ply namesp Revision 1.5 2004/05/12 10:19:30 ganovelli new line added at the end of file Revision 1.4 2004/05/04 02:36:07 ganovelli #ifndef __VCGLIB_IMPORTERPLY added Revision 1.3 2004/04/03 13:30:01 cignoni missing include allocate.h Revision 1.2 2004/03/09 21:26:47 cignoni cr lf mismatch Revision 1.1 2004/03/03 15:00:51 cignoni Initial commit ****************************************************************************/ #ifndef __VCGLIB_IMPORTERPLY #define __VCGLIB_IMPORTERPLY #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { template int PlyType () { return 0;} template <> int PlyType () { return ply::T_FLOAT; } template <> int PlyType () { return ply::T_DOUBLE; } template <> int PlyType () { return ply::T_INT; } template <> int PlyType () { return ply::T_SHORT; } template <> int PlyType () { return ply::T_UCHAR; } /** This class encapsulate a filter for opening ply meshes. The ply file format is quite extensible... */ template class ImporterPLY { public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::FaceIterator FaceIterator; //template int PlyType () { assert(0); return 0;} #define MAX_USER_DATA 256 // Struttura ausiliaria per la lettura del file ply struct LoadPly_FaceAux { unsigned char size; int v[512]; int flags; float q; float tcoord[32]; unsigned char ntcoord; int tcoordind; float colors[32]; unsigned char ncolors; unsigned char r; unsigned char g; unsigned char b; unsigned char data[MAX_USER_DATA]; }; struct LoadPly_TristripAux { int size; int *v; unsigned char data[MAX_USER_DATA]; }; // Struttura ausiliaria per la lettura del file ply template struct LoadPly_VertAux { S p[3]; int flags; float q; unsigned char r; unsigned char g; unsigned char b; unsigned char data[MAX_USER_DATA]; }; // Struttura ausiliaria caricamento camera struct LoadPly_Camera { float view_px; float view_py; float view_pz; float x_axisx; float x_axisy; float x_axisz; float y_axisx; float y_axisy; float y_axisz; float z_axisx; float z_axisy; float z_axisz; float focal; float scalex; float scaley; float centerx; float centery; int viewportx; int viewporty; float k1; float k2; float k3; float k4; }; static const PropDescriptor &VertDesc(int i) { const static PropDescriptor pv[9]={ {"vertex", "x", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p[0]),0,0,0,0,0}, {"vertex", "y", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p[1]),0,0,0,0,0}, {"vertex", "z", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p[2]),0,0,0,0,0}, {"vertex", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_VertAux,flags),0,0,0,0,0}, {"vertex", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux,q),0,0,0,0,0}, {"vertex", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,r),0,0,0,0,0}, {"vertex", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,g),0,0,0,0,0}, {"vertex", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,b),0,0,0,0,0}, {"vertex", "confidence",ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux,q),0,0,0,0,0}, }; return pv[i]; } static const PropDescriptor &FaceDesc(int i) { const static PropDescriptor qf[12]= { {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,size) }, {"face", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,flags), 0,0,0,0,0}, {"face", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,q), 0,0,0,0,0}, {"face", "texcoord", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,tcoord), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,ntcoord) }, {"face", "color", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,colors), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,ncolors) }, {"face", "texnumber", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,tcoordind), 0,0,0,0,0}, {"face", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,r), 0,0,0,0,0}, {"face", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,g), 0,0,0,0,0}, {"face", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,b), 0,0,0,0,0}, {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR,ply::T_CHAR,offsetof(LoadPly_FaceAux,size) }, {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR,ply::T_CHAR,offsetof(LoadPly_FaceAux,size) }, {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR,ply::T_CHAR,offsetof(LoadPly_FaceAux,size) }, }; return qf[i]; } static const PropDescriptor &TristripDesc(int i) { const static PropDescriptor qf[1]= { {"tristrips","vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_TristripAux,v), 1,1,ply::T_INT,ply::T_INT,offsetof(LoadPly_TristripAux,size) }, }; return qf[i]; } static const PropDescriptor &CameraDesc(int i) { const static PropDescriptor cad[23] = { {"camera","view_px",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_px),0,0,0,0,0}, {"camera","view_py",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_py),0,0,0,0,0}, {"camera","view_pz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_pz),0,0,0,0,0}, {"camera","x_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisx),0,0,0,0,0}, {"camera","x_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisy),0,0,0,0,0}, {"camera","x_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisz),0,0,0,0,0}, {"camera","y_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisx),0,0,0,0,0}, {"camera","y_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisy),0,0,0,0,0}, {"camera","y_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisz),0,0,0,0,0}, {"camera","z_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisx),0,0,0,0,0}, {"camera","z_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisy),0,0,0,0,0}, {"camera","z_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisz),0,0,0,0,0}, {"camera","focal" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,focal ),0,0,0,0,0}, {"camera","scalex" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scalex ),0,0,0,0,0}, {"camera","scaley" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scaley ),0,0,0,0,0}, {"camera","centerx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centerx),0,0,0,0,0}, {"camera","centery",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centery),0,0,0,0,0}, {"camera","viewportx",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewportx),0,0,0,0,0}, {"camera","viewporty",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewporty),0,0,0,0,0}, {"camera","k1" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k1 ),0,0,0,0,0}, {"camera","k2" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k2 ),0,0,0,0,0}, {"camera","k3" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k3 ),0,0,0,0,0}, {"camera","k4" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k4 ),0,0,0,0,0} }; return cad[i]; } /// Standard call for knowing the meaning of an error code static const char *ErrorMsg(int error) { static std::vector ply_error_msg; if(ply_error_msg.empty()) { ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS ); ply_error_msg[ply::E_NOERROR ]="No errors"; ply_error_msg[ply::E_CANTOPEN ]="Can't open file"; ply_error_msg[ply::E_NOTHEADER ]="Header not found"; ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header"; ply_error_msg[ply::E_NOFORMAT ]="Format not found"; ply_error_msg[ply::E_SYNTAX ]="Syntax error on header"; ply_error_msg[ply::E_PROPOUTOFELEMENT]="Property without element"; ply_error_msg[ply::E_BADTYPENAME ]="Bad type name"; ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found"; ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found"; ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread"; ply_error_msg[ply::E_INCOMPATIBLETYPE]="Incompatible type"; ply_error_msg[ply::E_BADCAST ]="Bad cast"; ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found"; ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found"; ply_error_msg[PlyInfo::E_SHORTFILE ]="Unespected eof"; ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices"; ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face"; ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates"; ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices"; } if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error"; else return ply_error_msg[error].c_str(); }; /// Standard call for reading a mesh static int Open( OpenMeshType &m, const char * filename, CallBackPos *cb=0) { PlyInfo pi; pi.cb=cb; return Open(m, filename, pi); } /// Read a mesh and store in loadmask the loaded field static int Open( OpenMeshType &m, const char * filename, int & loadmask, CallBackPos *cb =0) { PlyInfo pi; pi.mask=loadmask; return Open(m, filename,pi); loadmask=pi.mask; } /// read a mesh with all the possible option specified in the PlyInfo obj. static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi ) { assert(filename!=0); std::vector index; LoadPly_FaceAux fa; LoadPly_TristripAux tsa; LoadPly_VertAux va; pi.mask = 0; bool multit = false; // true if texture has a per face int spec the texture index va.flags = 42; pi.status = ::vcg::ply::E_NOERROR; // init defaults VertexType tv; tv.UberFlags() = 0; if( VertexType::HasQuality() ) tv.Q()=1.0; if( VertexType::HasColor() ) tv.C()=Color4b(Color4b::White); FaceType tf; tf.UberFlags() = 0; if( FaceType::HasFaceQuality() ) tf.Q()=1.0; if( FaceType::HasWedgeColor() ) tf.WC(0)=tf.WC(1)=tf.WC(2)=Color4b(Color4b::White); if( FaceType::HasFaceColor() ) tf.C()=Color4b(Color4b::White); // Descrittori delle strutture //bool isvflags = false; // Il file contiene i flags // The main descriptor of the ply file vcg::ply::PlyFile pf; // Open the file and parse the header if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 ) { pi.status = pf.GetError(); return pi.status; } pi.header = pf.GetHeader(); // Descrittori della camera { // Check that all the camera properties are present. bool found = true; for(int i=0;i<23;++i) { if( pf.AddToRead(CameraDesc(i))==-1 ) { found = false; break; } } if(found) pi.mask |= ply::PLYMask::PM_CAMERA; } // Descrittori dati standard (vertex coord e faces) if( pf.AddToRead(VertDesc(0))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; } if( pf.AddToRead(VertDesc(1))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; } if( pf.AddToRead(VertDesc(2))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; } if( pf.AddToRead(FaceDesc(0))==-1 ) // Se fallisce si prova anche la sintassi di rapidform con index al posto di indices if( pf.AddToRead(FaceDesc(9))==-1 ) if( pf.AddToRead(FaceDesc(10))==-1 ) if( pf.AddToRead(FaceDesc(11))==-1 ) if(pf.AddToRead(TristripDesc(0))==-1) // Se fallisce tutto si prova a vedere se ci sono tristrip alla levoy. { pi.status = PlyInfo::E_NO_FACE; return pi.status; } // Descrittori facoltativi dei flags if( pf.AddToRead(VertDesc(3))!=-1 ) pi.mask |= ply::PLYMask::PM_VERTFLAGS; if( VertexType::HasQuality() ) { if( pf.AddToRead(VertDesc(4))!=-1 || pf.AddToRead(VertDesc(8))!=-1 ) pi.mask |= ply::PLYMask::PM_VERTQUALITY; } if( VertexType::HasColor() ) { if( pf.AddToRead(VertDesc(5))!=-1 ) { pf.AddToRead(VertDesc(6)); pf.AddToRead(VertDesc(7)); pi.mask |= ply::PLYMask::PM_VERTCOLOR; } } // se ci sono i flag per vertice ci devono essere anche i flag per faccia if( pf.AddToRead(FaceDesc(1))!=-1 ) pi.mask |= ply::PLYMask::PM_FACEFLAGS; if( FaceType::HasFaceQuality()) { if( pf.AddToRead(FaceDesc(2))!=-1 ) pi.mask |= ply::PLYMask::PM_FACEQUALITY; } if( FaceType::HasFaceColor() ) { if( pf.AddToRead(FaceDesc(6))!=-1 ) { pf.AddToRead(FaceDesc(7)); pf.AddToRead(FaceDesc(8)); pi.mask |= ply::PLYMask::PM_FACECOLOR; } } if( FaceType::HasWedgeTexture() ) { if( pf.AddToRead(FaceDesc(3))!=-1 ) { if(pf.AddToRead(FaceDesc(5))==0) { multit=true; // try to read also the multi texture indicies pi.mask |= ply::PLYMask::PM_WEDGTEXMULTI; } pi.mask |= ply::PLYMask::PM_WEDGTEXCOORD; } } if( FaceType::HasWedgeColor() || FaceType::HasFaceColor() || VertexType::HasColor()) { if( pf.AddToRead(FaceDesc(4))!=-1 ) { pi.mask |= ply::PLYMask::PM_WEDGCOLOR; } } // Descrittori definiti dall'utente, std::vector VPV(pi.vdn); // property descriptor relative al tipo LoadPly_VertexAux std::vector FPV(pi.fdn); // property descriptor relative al tipo LoadPly_FaceAux if(pi.vdn>0){ // Compute the total size needed to load additional per vertex data. size_t totsz=0; for(int i=0;i,data)+totsz; totsz+=pi.VertexData[i].memtypesize(); if( pf.AddToRead(VPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; } } if(totsz > MAX_USER_DATA) { pi.status = vcg::ply::E_BADTYPE; return pi.status; } } if(pi.fdn>0){ size_t totsz=0; for(int i=0;i MAX_USER_DATA) { pi.status = vcg::ply::E_BADTYPE; return pi.status; } } /**************************************************************/ /* Main Reading Loop */ /**************************************************************/ m.Clear(); for(int i=0;i::AddVertices(m,n); for(j=0;j::AddFaces(m,n); pf.SetCurElement(i); for(j=0;j=m.vn ) { pi.status = PlyInfo::E_BAD_VERT_INDEX; return pi.status; } (*fi).V(k) = index[ fa.v[k] ]; } if( pi.mask & ply::PLYMask::PM_FACEFLAGS ) { (*fi).UberFlags() = fa.flags; } if( pi.mask & ply::PLYMask::PM_FACEQUALITY ) { (*fi).Q() = fa.q; } if( pi.mask & ply::PLYMask::PM_FACECOLOR ) { (*fi).C()[0] = fa.r; (*fi).C()[1] = fa.g; (*fi).C()[2] = fa.b; (*fi).C()[3] = 255; } if( pi.mask & ply::PLYMask::PM_WEDGTEXCOORD ) { for(int k=0;k<3;++k) { (*fi).WT(k).u() = fa.tcoord[k*2+0]; (*fi).WT(k).v() = fa.tcoord[k*2+1]; if(multit) (*fi).WT(k).n() = fa.tcoordind; } } if( pi.mask & ply::PLYMask::PM_WEDGCOLOR ) { if(FaceType::HasWedgeColor()){ for(int k=0;k<3;++k) { (*fi).WC(k)[0] = (unsigned char)(fa.colors[k*3+0]*255); (*fi).WC(k)[1] = (unsigned char)(fa.colors[k*3+1]*255); (*fi).WC(k)[2] = (unsigned char)(fa.colors[k*3+2]*255); } } if(FaceType::HasFaceColor()){ { (*fi).C()[0] = (unsigned char)((fa.colors[0*3+0]*255+fa.colors[1*3+0]*255+fa.colors[2*3+0]*255)/3.0f); (*fi).C()[1] = (unsigned char)((fa.colors[0*3+1]*255+fa.colors[1*3+1]*255+fa.colors[2*3+1]*255)/3.0f); (*fi).C()[2] = (unsigned char)((fa.colors[0*3+2]*255+fa.colors[1*3+2]*255+fa.colors[2*3+2]*255)/3.0f); } } } for(k=0;k=numvert_tmp ) { pi.status = PlyInfo::E_BAD_VERT_INDEX; return pi.status; } if(tsa.v[k+2]==-1) { k+=2; if(k%2) remainder=0; else remainder=1; continue; } tf.V(0) = index[ tsa.v[k+0] ]; tf.V(1) = index[ tsa.v[k+1] ]; tf.V(2) = index[ tsa.v[k+2] ]; if((k+remainder)%2) math::Swap (tf.V(0), tf.V(1) ); m.face.push_back( tf ); } } } else { // Skippaggio elementi non gestiti int n = pf.ElemNumber(i); pf.SetCurElement(i); for(int j=0;j32 && buf[i]<125 ) buf[j++] = buf[i]; // // buf[j] = 0; // char buf2[255]; // __interpret_texture_name( buf,filename,buf2 ); // textures.push_back( xstring(buf2) ); // } // if( !strncmp(c,NFILE,strlen(NFILE)) ) // { // strcpy(buf,c+strlen(NFILE)+1); // n = strlen(buf); // for(i=j=0;i32 && buf[i]<125 ) buf[j++] = buf[i]; // // buf[j] = 0; // char buf2[255]; // __interpret_texture_name( buf,filename,buf2 ); // normalmaps.push_back( xstring(buf2) ); // } //} // vn and fn should be correct but if someone wrongly saved some deleted elements they can be wrong. m.vn = 0; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( ! (*vi).IsD() ) ++m.vn; m.fn = 0; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if( ! (*fi).IsD() ) ++m.fn; return 0; } // Caricamento camera da un ply int LoadCamera(const char * filename) { vcg::ply::PlyFile pf; if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 ) { pi.status = pf.GetError(); return pi.status; } bool found = true; int i; for(i=0;i<23;++i) { if( pf.AddToRead(CameraDesc(i))==-1 ) { found = false; break; } } if(!found) return pi.status; for(i=0;i