import_ptx.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #ifndef __VCGLIB_IMPORT_PTX
00025 #define __VCGLIB_IMPORT_PTX
00026 
00027 #include <stdio.h>
00028 #include <wrap/callback.h>
00029 #include <vcg/complex/algorithms/clean.h>
00030 #include <vcg/complex/algorithms/update/normal.h>
00031 #include <vcg/complex/algorithms/update/position.h>
00032 #include <vcg/complex/algorithms/update/bounding.h>
00033 
00034 namespace vcg {
00035 namespace tri {
00036 namespace io {
00041 template <class OpenMeshType>
00042 class ImporterPTX
00043 {
00044 public:
00045   typedef typename OpenMeshType::VertexPointer VertexPointer;
00046   typedef typename OpenMeshType::ScalarType ScalarType;
00047   typedef typename OpenMeshType::VertexType VertexType;
00048   typedef typename OpenMeshType::FaceType FaceType;
00049   typedef typename OpenMeshType::VertexIterator VertexIterator;
00050   typedef typename OpenMeshType::FaceIterator FaceIterator;
00051   typedef typename OpenMeshType::CoordType CoordType;
00052   typedef typename vcg::Matrix44<ScalarType> Matrix44x;
00053 
00054   class Info            //ptx file info
00055   {
00056   public:
00057 
00058     Info()
00059     {
00060       mask                              = 0;
00061       meshnum                   = 0;
00062       anglecull         = true;
00063       angle                             = 89;
00064       savecolor         = true;
00065       pointcull         = true;
00066       pointsonly        = false;
00067       switchside        = false;
00068       flipfaces         = false;
00069     }
00070 
00072     int mask;
00073 
00075     int meshnum;
00076 
00078     bool anglecull;
00080     float angle;
00081 
00083     bool pointcull;
00084 
00086     bool pointsonly;
00087 
00089     bool savecolor;
00090 
00092     bool switchside;
00094     bool flipfaces;
00095 
00096   }; // end ptx file info class
00097 
00098 
00100   static const char *ErrorMsg(int error)
00101   {
00102     static const char * ptx_error_msg[] =
00103     {
00104       "No errors",
00105       "Can't open file",
00106       "Header not found",
00107       "Eof in header",
00108       "Format not found",
00109       "Syntax error on header",
00110     };
00111     if(error>6 || error<0) return "Unknown error";
00112     else return ptx_error_msg[error];
00113   };
00114 
00117   static bool skipmesh(FILE* fp, CallBackPos *cb=NULL)
00118   {
00119     int colnum;
00120     int rownum;
00121     int skiplines;
00122     char linebuf;
00123 
00124     if(feof(fp))        return false;
00125 
00126     // getting mesh size;
00127     fscanf(fp,"%i\n",&colnum);
00128     fscanf(fp,"%i\n",&rownum);
00129 
00130     if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
00131     if(feof(fp))        return false;
00132 
00133     // have to skip (col * row) lines plus 8 lines for the header
00134     skiplines = (colnum * rownum) + 8;
00135     for(int ii=0; ii<skiplines; ii++)
00136     {
00137       fread(&linebuf,1,1,fp);
00138       while(linebuf != '\n')  fread(&linebuf,1,1,fp);
00139     }
00140 
00141     if(cb) cb( 100, "Skipped preamble");
00142     return true;
00143   }
00144 
00146   static int Open( OpenMeshType &m, const char * filename, Info importparams, CallBackPos *cb=NULL)
00147   {
00148     FILE *fp;
00149     fp = fopen(filename, "rb");
00150     if(fp == NULL) return false;
00151     m.Clear();
00152     m.vn=0;
00153     m.fn=0;
00154 
00155     // if not exporting first one, skip meshes until desired one
00156     if (importparams.meshnum>0)
00157       for (int i=0; i!=importparams.meshnum; ++i)
00158         if(!skipmesh(fp, cb))
00159           return 1;
00160 
00161     if (!readPTX( m, fp, importparams, cb))
00162     {
00163       m.Clear();
00164       return 1;
00165     }
00166 
00167     return 0;
00168   }
00169 
00171   static bool readPTX( OpenMeshType &m, FILE *fp, Info importparams, CallBackPos *cb=NULL)
00172   {
00173     int numtokens;
00174     int colnum;
00175     int rownum;
00176     double xx,yy,zz;            // position
00177     float rr,gg,bb;             // color
00178     float rf;                                   // reflectance
00179     Matrix44d currtrasf;
00180 
00181     bool hascolor;
00182     bool savecolor   =  importparams.savecolor &&  VertexType::HasColor();
00183     bool switchside  =  importparams.switchside;
00184 
00185     int total = 50;
00186     if (importparams.pointsonly) total = 100;
00187     char linebuf[256];
00188 
00189     fscanf(fp,"%i\n",&colnum);
00190     fscanf(fp,"%i\n",&rownum);
00191 
00192     if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
00193     // initial 4 lines [still don't know what is this :) :)]
00194     if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00195     if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00196     if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00197     if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00198     // now the transformation matrix
00199     if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(0,0)), &(currtrasf.ElementAt(0,1)), &(currtrasf.ElementAt(0,2)), &(currtrasf.ElementAt(0,3))) )return false;
00200     if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(1,0)), &(currtrasf.ElementAt(1,1)), &(currtrasf.ElementAt(1,2)), &(currtrasf.ElementAt(1,3))) )return false;
00201     if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(2,0)), &(currtrasf.ElementAt(2,1)), &(currtrasf.ElementAt(2,2)), &(currtrasf.ElementAt(2,3))) )return false;
00202     if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(3,0)), &(currtrasf.ElementAt(3,1)), &(currtrasf.ElementAt(3,2)), &(currtrasf.ElementAt(3,3))) )return false;
00203 
00204     //now the real data begins
00205     // first line, we should know if the format is
00206     // XX YY ZZ RF
00207     // or it is
00208     // XX YY ZZ RF RR GG BB
00209     // read the entire first line and then count the spaces. it's rude but it works :)
00210     int ii=0;
00211     fread(&(linebuf[ii++]),1,1,fp);
00212     while(linebuf[ii-1] != '\n')  if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false;
00213     linebuf[ii-1] = '\0'; // terminate the string
00214     numtokens=1;
00215     for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++;
00216     if(numtokens == 4)  hascolor = false;
00217     else if(numtokens == 7)  hascolor = true;
00218     else  return false;
00219 
00220     // PTX transformation matrix is transposed
00221     currtrasf.transposeInPlace();
00222 
00223     // allocating vertex space
00224     int vn = rownum*colnum;
00225     VertexIterator vi = Allocator<OpenMeshType>::AddVertices(m,vn);
00226     m.vn = vn;
00227     m.bbox.SetNull();
00228 
00229     // parse the first line....
00230     if(hascolor)
00231     {
00232       printf("\n hascolor ");
00233       sscanf(linebuf,"%lf %lf %lf %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
00234     }
00235     else
00236     {
00237       printf("\n no color ");
00238       sscanf(linebuf,"%lf %lf %lf %f", &xx, &yy, &zz, &rf);
00239     }
00240 
00241     //addthefirstpoint
00242     (*vi).P()[0]=xx;
00243     (*vi).P()[1]=yy;
00244     (*vi).P()[2]=zz;
00245 
00246     if(VertexType::HasQuality())
00247     {
00248       (*vi).Q()=rf;
00249     }
00250 
00251     if(savecolor)
00252     {
00253       if(hascolor)
00254       {
00255         (*vi).C()[0]=rr;
00256         (*vi).C()[1]=gg;
00257         (*vi).C()[2]=bb;
00258       } else {
00259         (*vi).C()[0]=rf*255;
00260         (*vi).C()[1]=rf*255;
00261         (*vi).C()[2]=rf*255;
00262       }
00263     }
00264     vi++;
00265 
00266     if(switchside) std::swap(rownum,colnum);
00267 
00268     // now for each line until end of mesh (row*col)-1
00269     for(ii=0; ii<((rownum*colnum)-1); ii++)
00270     {
00271       if(cb && (ii%100)==0) cb((ii*total)/vn, "Vertex Loading");
00272 
00273       // read the stream
00274       if(hascolor)
00275         fscanf(fp,"%lf %lf %lf %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
00276       else
00277         fscanf(fp,"%lf %lf %lf %f", &xx, &yy, &zz, &rf);
00278 
00279       // add the point
00280       (*vi).P()[0]=xx;
00281       (*vi).P()[1]=yy;
00282       (*vi).P()[2]=zz;
00283 
00284 
00285       if(tri::HasPerVertexQuality(m)) (*vi).Q()=rf;
00286 
00287       if(hascolor && savecolor)
00288       {
00289         (*vi).C()[0]=rr;
00290         (*vi).C()[1]=gg;
00291         (*vi).C()[2]=bb;
00292       }
00293       else if(!hascolor && savecolor)
00294       {
00295         (*vi).C()[0]=rf*255;
00296         (*vi).C()[1]=rf*255;
00297         (*vi).C()[2]=rf*255;
00298       }
00299 
00300       vi++;
00301     }
00302 
00303     if(! importparams.pointsonly)
00304     {
00305       // now i can triangulate
00306       int trinum = (rownum-1) * (colnum-1) * 2;
00307       typename OpenMeshType::FaceIterator fi= Allocator<OpenMeshType>::AddFaces(m,trinum);
00308       int v0i,v1i,v2i, t;
00309       t=0;
00310       for(int rit=0; rit<rownum-1; rit++)
00311         for(int cit=0; cit<colnum-1; cit++)
00312         {
00313           t++;
00314           if(cb) cb(50 + (t*50)/(rownum*colnum),"PTX Mesh Loading");
00315 
00316           v0i = (rit  ) + ((cit  ) * rownum);
00317           v1i = (rit+1) + ((cit  ) * rownum);
00318           v2i = (rit  ) + ((cit+1) * rownum);
00319 
00320           // upper tri
00321           (*fi).V(2) = &(m.vert[v0i]);
00322           (*fi).V(1) = &(m.vert[v1i]);
00323           (*fi).V(0) = &(m.vert[v2i]);
00324 
00325           fi++;
00326 
00327           v0i = (rit+1) + ((cit  ) * rownum);
00328           v1i = (rit+1) + ((cit+1) * rownum);
00329           v2i = (rit  ) + ((cit+1) * rownum);
00330 
00331           // lower tri
00332           (*fi).V(2) = &(m.vert[v0i]);
00333           (*fi).V(1) = &(m.vert[v1i]);
00334           (*fi).V(0) = &(m.vert[v2i]);
00335 
00336           fi++;
00337         }
00338     }
00339     printf("Loaded %i vert\n",m.vn);
00340     // remove unsampled points
00341     if(importparams.pointcull)
00342     {
00343       if(cb) cb(40,"PTX Mesh Loading - remove invalid vertices");
00344       for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++)
00345       {
00346         if((*vi).P() == CoordType(0.0, 0.0, 0.0))
00347           Allocator<OpenMeshType>::DeleteVertex(m,*vi);
00348       }
00349 
00350       if(! importparams.pointsonly)
00351       {
00352         if(cb) cb(60,"PTX Mesh Loading - remove invalid faces");
00353         for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
00354         {
00355           if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) )
00356             Allocator<OpenMeshType>::DeleteFace(m,*fi);
00357         }
00358       }
00359     }
00360 
00361     float limitCos = cos( math::ToRad(importparams.angle) );
00362     printf("Loaded %i vert\n",m.vn);
00363     if(importparams.pointsonly)
00364     { // Compute Normals and radius for points
00365       // Compute the four edges around each point
00366       // Some edges can be null (boundary and invalid samples)
00367       if(cb) cb(85,"PTX Mesh Loading - computing vert normals");
00368       for(int rit=0; rit<rownum; rit++)
00369       {
00370         int ritL = std::max(rit-1,0);
00371         int ritR = std::min(rit+1,rownum-1);
00372         for(int cit=0; cit<colnum; cit++)
00373         {
00374           int citT = std::max(cit-1,0);
00375           int citB = std::min(cit+1,colnum-1);
00376           int v0 = (rit ) + ((cit ) * rownum);
00377 
00378           if(m.vert[v0].IsD()) continue;
00379 
00380           int vL = (ritL) + ((cit ) * rownum);
00381           int vR = (ritR) + ((cit) * rownum);
00382           int vT = (rit ) + ((citT ) * rownum);
00383           int vB = (rit ) + ((citB) * rownum);
00384 
00385           CoordType v0p=m.vert[v0].P();
00386           CoordType vLp(0,0,0),vRp(0,0,0),vTp(0,0,0),vBp(0,0,0);  // Compute the 4 edges around the vertex.
00387           if(!m.vert[vL].IsD()) vLp=(m.vert[vL].P()-v0p).Normalize();
00388           if(!m.vert[vR].IsD()) vRp=(m.vert[vR].P()-v0p).Normalize();
00389           if(!m.vert[vT].IsD()) vTp=(m.vert[vT].P()-v0p).Normalize();
00390           if(!m.vert[vB].IsD()) vBp=(m.vert[vB].P()-v0p).Normalize();
00391           float r=0;
00392           int rc=0; CoordType v0pn = Normalize(v0p);
00393           // Skip edges that are too steep
00394           // Compute the four normalized vector orthogonal to each pair of consecutive edges.
00395           CoordType vLTn =  (vLp ^ vTp).Normalize();
00396           CoordType vTRn =  (vTp ^ vRp).Normalize();
00397           CoordType vRBn =  (vRp ^ vBp).Normalize();
00398           CoordType vBLn =  (vBp ^ vLp).Normalize();
00399 
00400           // Compute an average Normal skipping null normals and normals that are too steep.
00401           // Compute also the sum of non null edge lenght to compute the radius
00402           CoordType N(0,0,0);
00403           if((vLTn*v0pn)>limitCos)  { N+=vLTn; r += Distance(m.vert[vL].P(),v0p)+Distance(m.vert[vT].P(),v0p); rc++; }
00404           if((vTRn*v0pn)>limitCos)  { N+=vTRn; r += Distance(m.vert[vT].P(),v0p)+Distance(m.vert[vR].P(),v0p); rc++; }
00405           if((vRBn*v0pn)>limitCos)  { N+=vRBn; r += Distance(m.vert[vR].P(),v0p)+Distance(m.vert[vB].P(),v0p); rc++; }
00406           if((vBLn*v0pn)>limitCos)  { N+=vBLn; r += Distance(m.vert[vB].P(),v0p)+Distance(m.vert[vL].P(),v0p); rc++; }
00407 
00408           m.vert[v0].N()=-N;
00409 
00410           if(tri::HasPerVertexRadius(m)) m.vert[v0].R() = r/(rc*2.0f);
00411           // Isolated points has null normal. Delete them please.
00412           if(m.vert[v0].N() == CoordType(0,0,0)) Allocator<OpenMeshType>::DeleteVertex(m,m.vert[v0]);
00413         }
00414       }
00415     }
00416     else
00417       // eliminate high angle triangles
00418     {
00419       if(importparams.flipfaces)
00420         tri::Clean<OpenMeshType>::FlipMesh(m);
00421       if(importparams.anglecull)
00422       {
00423         if(cb) cb(85,"PTX Mesh Loading - remove steep faces");
00424         tri::UpdateNormal<OpenMeshType>::PerFaceNormalized(m);
00425         for(FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
00426           if(!(*fi).IsD())
00427           {
00428             CoordType raggio = -((*fi).P(0) + (*fi).P(1) + (*fi).P(2)) / 3.0;
00429             raggio.Normalize();
00430             if((raggio.dot((*fi).N())) < limitCos)
00431               Allocator<OpenMeshType>::DeleteFace(m,*fi);
00432           }
00433         // deleting unreferenced vertices only if we are interested in faces...
00434         tri::Clean<OpenMeshType>::RemoveUnreferencedVertex(m);
00435       }
00436     }
00437     Matrix44x tr; 
00438     tr.Import(currtrasf);
00439     tri::UpdatePosition<OpenMeshType>::Matrix(m,tr,true);
00440     tri::Allocator<OpenMeshType>::CompactVertexVector(m);
00441     tri::UpdateBounding<OpenMeshType>::Box(m);
00442     if(cb) cb(100,"PTX Mesh Loading finished!");
00443     return true;
00444   }
00445 
00446 }; // end class
00447 
00448 } // end Namespace tri
00449 } // end Namespace io
00450 } // end Namespace vcg
00451 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:31:58