import_off.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 #ifndef __VCGLIB_IMPORT_OFF
00024 #define __VCGLIB_IMPORT_OFF
00025 
00026 #include <fstream>
00027 #include<vcg/complex/algorithms/bitquad_support.h>
00028 #include <wrap/io_trimesh/io_mask.h>
00029 #include <wrap/io_trimesh/io_fan_tessellator.h>
00030 
00031 namespace vcg {
00032 namespace tri {
00033 namespace io {
00034 
00035 // /** \addtogroup  */
00036 // /* @{ */
00041 template<class MESH_TYPE>
00042 class ImporterOFF
00043 {
00044 public:
00045 
00046   typedef typename MESH_TYPE::VertexType                        VertexType;
00047   typedef typename MESH_TYPE::VertexIterator    VertexIterator;
00048   typedef typename MESH_TYPE::VertexPointer             VertexPointer;
00049   typedef typename MESH_TYPE::FaceType                          FaceType;
00050   typedef typename MESH_TYPE::FaceIterator              FaceIterator;
00051   typedef typename MESH_TYPE::FacePointer                       FacePointer;
00052   typedef typename MESH_TYPE::CoordType                         CoordType;
00053   typedef typename MESH_TYPE::ScalarType                        ScalarType;
00054 
00055   // OFF codes
00056   enum OFFCodes {NoError=0, CantOpen, InvalidFile,
00057                  InvalidFile_MissingOFF,
00058                  UnsupportedFormat, ErrorNotTriangularFace,ErrorHighDimension,ErrorDegenerateFace};
00059 
00065   static const char* ErrorMsg(int message_code)
00066   {
00067     static const char* error_msg[] =
00068     {
00069       "No errors", "Can't open file", "Invalid file",
00070       "Invalid file: OFF file should have in the first line the OFF keyword as a first token",
00071       "Unsupported format", "Face with more than 3 vertices","File with high dimensional vertexes are not supported", "Error Degenerate Face with less than 3 vertices"                         };
00072 
00073     if(message_code>6 || message_code<0)
00074       return "Unknown error";
00075     else
00076       return error_msg[message_code];
00077   };
00078 
00086   static bool LoadMask(const char *filename, int &loadmask)
00087   {
00088     // To obtain the loading mask all the file must be parsed
00089     // to distinguish between per-vertex and per-face color attribute.
00090     loadmask=0;
00091     MESH_TYPE dummyMesh;
00092     return (Open(dummyMesh, filename, loadmask)==NoError);
00093   }
00094 
00095   static int Open(MESH_TYPE &mesh, const char *filename,CallBackPos *cb=0)
00096   {
00097     int loadmask;
00098     return Open(mesh,filename,loadmask,cb);
00099   }
00100 
00101   static int OpenMem(MESH_TYPE &mesh, const char *mem, size_t sz, int &loadmask,
00102                   CallBackPos *cb=0)
00103   {
00104     std::string str;
00105     str.append(mem,sz);
00106     std::istringstream strm(str);
00107     return OpenStream(mesh,strm,loadmask,cb);
00108   }
00109 
00117   static int Open(MESH_TYPE &mesh, const char *filename, int &loadmask,
00118                   CallBackPos *cb=0)
00119   {
00120     std::ifstream stream(filename);
00121     if (stream.fail())
00122       return CantOpen;
00123     return OpenStream(mesh,stream,loadmask,cb);
00124   }
00125 
00126     static int OpenStream(MESH_TYPE &mesh, std::istream &stream, int &loadmask,
00127                     CallBackPos *cb=0)
00128     {
00129     std::vector< std::string > tokens;
00130     TokenizeNextLine(stream, tokens);
00131     if(tokens.empty()) return InvalidFile_MissingOFF;
00132 
00133     bool isNormalDefined   = false;
00134     bool isColorDefined    = false;
00135     bool isTexCoordDefined = false;
00136     int dimension = 3;
00137     bool homogeneousComponents = false;
00138 
00139 
00140     /*
00141     [ST][C][N][4][n]OFF # Header keyword
00142     [Ndim]              # Space dimension of vertices, present only if nOFF
00143     NVertices  NFaces  NEdges   # NEdges not used or checked
00144 
00145     x[0]  y[0]  z[0]    # Vertices, possibly with normals, colors, and/or texture coordinates, in that order,  if the prefixes N, C, ST are present.
00146     # If 4OFF, each vertex has 4 components including a final homogeneous component.
00147     # If nOFF, each vertex has Ndim components.
00148     # If 4nOFF, each vertex has Ndim+1 components.
00149     ...
00150     x[NVertices-1]  y[NVertices-1]  z[NVertices-1]
00151 
00152     # Faces
00153     # Nv = # vertices on this face
00154     # v[0] ... v[Nv-1]: vertex indices
00155     #           in range 0..NVertices-1
00156     Nv  v[0] v[1] ... v[Nv-1]  colorspec
00157     ...
00158     # colorspec continues past v[Nv-1] to end-of-line; may be 0 to 4 numbers
00159     # nothing: default
00160     # integer: colormap index
00161     # 3 or 4 integers: RGB[A] values 0..255
00162     # 3 or 4 floats: RGB[A] values 0..1
00163     */
00164     std::string header = tokens[0];
00165     if (header.rfind("OFF") != std::basic_string<char>::npos)
00166     { // the OFF string is in the header go on parsing it.
00167       for (int u = static_cast<int>(header.rfind("OFF")-1); u>=0; u--)
00168       {
00169         if      (header[u] == 'C')                              isColorDefined = true;
00170         else if (header[u] == 'N')                              isNormalDefined = true;
00171         else if (u>0 && header[u-1] == 'S' && header[u] == 'T') isTexCoordDefined = true;
00172         else if (header[u] == '4')                              homogeneousComponents = true;
00173         else if (header[u] == 'n') return ErrorHighDimension;
00174       }
00175     }
00176     else return InvalidFile_MissingOFF;
00177 
00178     // If the file is slightly malformed and it has nvert and nface AFTER the OFF string instead of in the next line
00179     // we manage it here...
00180     if(tokens.size()==1) TokenizeNextLine(stream, tokens);
00181     else tokens.erase(tokens.begin(),tokens.begin()+1);
00182 
00183     // Update loading mask
00185 
00186     loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
00187 
00188     if (isNormalDefined)                loadmask |= Mask::IOM_VERTNORMAL;
00189     if (isTexCoordDefined)      loadmask |= Mask::IOM_VERTTEXCOORD;
00190     if (isColorDefined)                 { loadmask |= Mask::IOM_VERTCOLOR;loadmask |= Mask::IOM_FACECOLOR;}
00191 
00192 
00193     //if(onlyMaskFlag) return NoError;
00194 
00195 
00196     mesh.Clear();
00197 
00198     // check on next 2 lines to detect corrupted files
00199     if(tokens.size() < 3)
00200       return InvalidFile;
00201 
00202     unsigned int nVertices, nFaces, nEdges;
00203     nVertices = atoi(tokens[0].c_str());
00204     nFaces    = atoi(tokens[1].c_str());
00205     nEdges    = atoi(tokens[2].c_str());
00206 
00207     // dimension is the space dimension of vertices => it must be three(!)
00208     if (dimension != 3)
00209       return UnsupportedFormat;
00210 
00211     if (homogeneousComponents)
00212       return UnsupportedFormat;
00213 
00214     // READ VERTICES
00216 
00217     VertexIterator v_iter = Allocator<MESH_TYPE>::AddVertices(mesh, nVertices);
00218     TokenizeNextLine(stream, tokens);
00219     size_t k = 0; // next token to read
00220 
00221     for (unsigned int i=0; i<nVertices; i++, v_iter++)
00222     {
00223       if (cb && (i%1000)==0)
00224         cb(i*50/nVertices, "Vertex Loading");
00225 
00226       // Read 3 vertex coordinates
00227       for (unsigned int j=0; j<3; j++)
00228       {
00229         // Go to next line when needed
00230         if (k == tokens.size())   // if EOL
00231         {
00232           TokenizeNextLine(stream, tokens);
00233           if (tokens.size() == 0) // if EOF
00234             return InvalidFile;
00235           k = 0;
00236         }
00237 
00238         // Read vertex coordinate
00239         (*v_iter).P()[j] = (ScalarType) atof(tokens[k].c_str());
00240         k++;
00241       }
00242 
00243       if (isNormalDefined)
00244       {
00245         // Read 3 normal coordinates
00246         for (unsigned int j=0; j<3; j++)
00247         {
00248           // Go to next line when needed
00249           if (k == tokens.size())   // if EOL
00250           {
00251             TokenizeNextLine(stream, tokens);
00252             if (tokens.size() == 0) // if EOF
00253               return InvalidFile;
00254             k = 0;
00255           }
00256 
00257           // Read normal coordinate
00258           (*v_iter).N()[j] = (ScalarType) atof(tokens[k].c_str());
00259           k++;
00260         }
00261       }
00262 
00263       // NOTE: It is assumed that colored vertex takes exactly one text line
00264       //       (otherwise it is impossible to parse color information since
00265       //        color components can vary)
00266       if (isColorDefined)
00267       {
00268         // The number of color components varies from 0 to 4.
00269         // The OFF format guaranties that there is 1 vertex per line.
00270         int nb_color_components = static_cast<int>(tokens.size())
00271             - static_cast<int>(k) /* tokens already parsed */
00272             - 2 * (isTexCoordDefined ? 1 : 0);
00273 
00274         if (nb_color_components < 0 || nb_color_components > 4)
00275           return InvalidFile;
00276 
00277         // set per-vertex color attribute
00278         if (nb_color_components > 0)
00279           loadmask |= Mask::IOM_VERTCOLOR;
00280 
00281         // Store color components
00282         if (tri::HasPerVertexColor(mesh))
00283         {
00284           // Read color components
00285 
00286           if (nb_color_components == 1)
00287           {
00288             // read color index
00289             (*v_iter).C().Import(ColorMap(atoi(tokens[k].c_str())));
00290           }
00291           else if (nb_color_components == 3)
00292           {
00293             // read RGB color
00294             if (tokens[k].find(".") == size_t(-1))// if it is a float there is a dot
00295             {
00296               // integers
00297               unsigned char r =
00298                   static_cast<unsigned char>(atoi(tokens[k].c_str()));
00299               unsigned char g =
00300                   static_cast<unsigned char>(atoi(tokens[k+1].c_str()));
00301               unsigned char b =
00302                   static_cast<unsigned char>(atoi(tokens[k+2].c_str()));
00303 
00304               vcg::Color4b color(r, g, b, 255);
00305               (*v_iter).C().Import(color);
00306             }
00307             else
00308             {
00309               // floats
00310               float r = static_cast<float>(atof(tokens[k].c_str()));
00311               float g = static_cast<float>(atof(tokens[k+1].c_str()));
00312               float b = static_cast<float>(atof(tokens[k+2].c_str()));
00313 
00314               vcg::Color4f color(r, g, b, 1.0);
00315               (*v_iter).C().Import(color);
00316             }
00317           }
00318           else if (nb_color_components == 4)
00319           {
00320             // read RGBA color
00321             if (tokens[k].find(".") == size_t(-1))
00322             {
00323               // integers
00324               unsigned char r =
00325                   static_cast<unsigned char>(atoi(tokens[k].c_str()));
00326               unsigned char g =
00327                   static_cast<unsigned char>(atoi(tokens[k+1].c_str()));
00328               unsigned char b =
00329                   static_cast<unsigned char>(atoi(tokens[k+2].c_str()));
00330               unsigned char a =
00331                   static_cast<unsigned char>(atoi(tokens[k+3].c_str()));
00332 
00333               Color4b color(r, g, b, a);
00334               (*v_iter).C().Import(color);
00335             }
00336             else
00337             {
00338               // floats
00339               float r = static_cast<float>(atof(tokens[k].c_str()));
00340               float g = static_cast<float>(atof(tokens[k+1].c_str()));
00341               float b = static_cast<float>(atof(tokens[k+2].c_str()));
00342               float a = static_cast<float>(atof(tokens[k+3].c_str()));
00343 
00344               vcg::Color4f color(r, g, b, a);
00345               (*v_iter).C().Import(color);
00346             }
00347           }
00348         }
00349 
00350         k += nb_color_components;
00351       }
00352 
00353       if (isTexCoordDefined)
00354       {
00355         for (unsigned int j=0; j<2; j++)
00356         {
00357           // Go to next line when needed
00358           if (k == tokens.size())   // if EOL
00359           {
00360             TokenizeNextLine(stream, tokens);
00361             if (tokens.size() == 0) // if EOF
00362               return InvalidFile;
00363             k = 0;
00364           }
00365 
00366           std::string str = tokens[k];
00367           k++;
00368 
00369           // Store texture coordinates
00370           if (tri::HasPerWedgeTexCoord(mesh))
00371           {
00372             //...TODO...
00373           }
00374         }
00375       }
00376     } // for i=...
00377 
00378     // READ FACES
00380     if(FaceType::HasPolyInfo())
00381     {
00382       for (unsigned int f=0; f < nFaces; f++)
00383       {
00384         if(cb && (f%1000)==0) cb(50+f*50/nFaces,"Face Loading");
00385         TokenizeNextLine(stream, tokens);
00386         int vert_per_face = atoi(tokens[0].c_str());
00387         std::vector<int> vInd(vert_per_face);
00388         k = 1;
00389         for (int j=0; j < vert_per_face; j++)
00390         {
00391           if (k == tokens.size())   // if EOL // Go to next line when needed
00392           {
00393             TokenizeNextLine(stream, tokens);
00394             if (tokens.size() == 0) return InvalidFile; // if EOF
00395             k = 0;
00396           }
00397           vInd[j] = atoi(tokens[k].c_str());
00398           k++;
00399         }
00400         if(vert_per_face==3)
00401           Allocator<MESH_TYPE>::AddFace(mesh, &mesh.vert[ vInd[0] ], &mesh.vert[ vInd[1] ], &mesh.vert[ vInd[2] ]);
00402 
00403         if(vert_per_face==4)
00404           Allocator<MESH_TYPE>::AddQuadFace(mesh, &mesh.vert[ vInd[0] ], &mesh.vert[ vInd[1] ], &mesh.vert[ vInd[2] ],&mesh.vert[ vInd[3] ]);
00405 
00406       }
00407     }
00408     else // Standard Triangular Mesh Loading
00409     {
00410       Allocator<MESH_TYPE>::AddFaces(mesh, nFaces);
00411       unsigned int f0=0;
00412 
00413 
00414       // Initial call to the QuadTriangulate with an empty vector to just reset the static set of existing diagonals
00415       std::vector<VertexPointer> qtmp;
00416       BitQuad<MESH_TYPE>::QuadTriangulate(qtmp);
00417 
00418       for (unsigned int f=0; f < nFaces; f++)
00419       {
00420         f0 = f;
00421         if (stream.fail())
00422           return InvalidFile;
00423 
00424         if(cb && (f%1000)==0)
00425           cb(50+f*50/nFaces,"Face Loading");
00426 
00427         TokenizeNextLine(stream, tokens);
00428         int vert_per_face = atoi(tokens[0].c_str());
00429         if(vert_per_face < 3)
00430           return ErrorDegenerateFace;
00431         k = 1;
00432         if (vert_per_face == 3)
00433         {
00434           for (int j = 0; j < 3; j++)
00435           {
00436             if (k == tokens.size())   // if EOL                 // Go to next line when needed
00437             {
00438               TokenizeNextLine(stream, tokens);
00439               if (tokens.size() == 0) return InvalidFile; // if EOF
00440               k = 0;
00441             }
00442 
00443             mesh.face[f].V(j) = &(mesh.vert[ atoi(tokens[k].c_str()) ]);
00444             k++;
00445           }
00446         }
00447         else
00448         {
00449           // The face must be triangulated
00450           unsigned int trigs = vert_per_face-3; // number of extra faces to add
00451           nFaces += trigs;
00452           Allocator<MESH_TYPE>::AddFaces(mesh, trigs);
00453           std::vector<int> vertIndices(vert_per_face);
00454           std::vector<vcg::Point3f > polygonVect(vert_per_face); // vec of polygon loops used for the triangulation of polygonal face
00455           for (int j=0; j < vert_per_face; j++)
00456           {
00457             if (k == tokens.size())   // if EOL // Go to next line when needed
00458             {
00459               TokenizeNextLine(stream, tokens);
00460               if (tokens.size() == 0) return InvalidFile; // if EOF
00461               k = 0;
00462             }
00463             vertIndices[j] = atoi(tokens[k].c_str());
00464             polygonVect[j].Import<ScalarType> (mesh.vert[ vertIndices[j] ].P());
00465             k++;
00466           }
00467           if(vert_per_face==4)
00468           {   // To well triangulate use the bitquad support function that reorders vertex for a simple fan
00469             std::vector<VertexPointer> q(4);
00470             for(int qqi=0;qqi<4;++qqi)
00471               q[qqi]=& mesh.vert[vertIndices[qqi]];
00472             BitQuad<MESH_TYPE>::QuadTriangulate(q);
00473             for(int qqi=0;qqi<4;++qqi)
00474               vertIndices[qqi] = q[qqi]- & mesh.vert[0];
00475             // build a two face fan
00476             for (int j=0; j<2; j++)
00477             {
00478               mesh.face[f+j].V(0) = &(mesh.vert[ vertIndices[0  ] ]);
00479               mesh.face[f+j].V(1) = &(mesh.vert[ vertIndices[1+j] ]);
00480               mesh.face[f+j].V(2) = &(mesh.vert[ vertIndices[2+j] ]);
00481               if (tri::HasPerFaceFlags(mesh)) {
00482                 // tag internal polygonal edges as "faux"
00483                 if (j>0) mesh.face[f+j].SetF(0);
00484                 if (j<vert_per_face-3) mesh.face[f+j].SetF(2);
00485                 loadmask |= Mask::IOM_BITPOLYGONAL;
00486               }
00487             }
00488           }
00489           else // standard fan triangulation (we hope the polygon is convex...)
00490           {
00491             std::vector<int> indexTriangulatedVect;
00492             //                              TessellatePlanarPolygon3(polygonVect,indexTriangulatedVect);
00493             std::vector< std::vector<Point3f> > loopVect;
00494             loopVect.push_back(polygonVect);
00495 #ifdef __gl_h_
00496             //qDebug("OK: using opengl tessellation for a polygon of %i vertices",vertexesPerFace);
00497             vcg::glu_tesselator::tesselate<vcg::Point3f>(loopVect, indexTriangulatedVect);
00498 #else
00499             //qDebug("Warning: using fan tessellation for a polygon of %i vertices",vertexesPerFace);
00500             tri::io::FanTessellator(loopVect, indexTriangulatedVect);
00501 #endif
00502             for (size_t j=0; j<indexTriangulatedVect.size(); j+=3)
00503             {
00504               mesh.face[f+j/3].V(0) = &(mesh.vert[ vertIndices[ indexTriangulatedVect[j+0] ] ]);
00505               mesh.face[f+j/3].V(1) = &(mesh.vert[ vertIndices[ indexTriangulatedVect[j+1] ] ]);
00506               mesh.face[f+j/3].V(2) = &(mesh.vert[ vertIndices[ indexTriangulatedVect[j+2] ] ]);
00507               // To correctly set Faux edges we have to clear the faux bit for all the edges that do not correspond to consecutive vertices
00508               // Consecutivity is in the space of the index of the polygon.
00509               for(int qq=0;qq<3;++qq)
00510               {
00511                 if( (indexTriangulatedVect[j+qq]+1)%vert_per_face == indexTriangulatedVect[j+(qq+1)%3])
00512                   mesh.face[f+j/3].ClearF(qq);
00513                 else mesh.face[f+j/3].SetF(qq);
00514               }
00515             }
00516           }
00517           f+=trigs;
00518         }
00519 
00520         // NOTE: It is assumed that colored face takes exactly one text line
00521         //       (otherwise it is impossible to parse color information since
00522         //        color components can vary)
00523         size_t color_elements = tokens.size() - vert_per_face-1;
00524         isColorDefined |= (color_elements>0);
00525         if(isColorDefined) loadmask |= Mask::IOM_FACECOLOR;
00526 
00527         if( (color_elements>0)  && tri::HasPerFaceColor(mesh) )
00528         {
00529 
00530 
00531           // set per-face color attribute
00532           if (color_elements > 0)
00533             loadmask |= Mask::IOM_FACECOLOR;
00534 
00535           switch (color_elements)
00536           {
00537           case 0:
00538           {
00539             for ( ; f0<=f; f0++)
00540               mesh.face[f0].C().Import(vcg::Color4f(.666f, .666f, .666f, .666f));
00541             break;
00542           }
00543           case 1:
00544           {
00545             for ( ; f0<=f; f0++)
00546               mesh.face[f0].C().Import( ColorMap( atoi(tokens[vert_per_face+1].c_str()) ) );
00547             break;
00548           }
00549           case 3:
00550           {
00551             if (tokens[vert_per_face+1].find('.')==std::string::npos) // if there is a float there is a dot
00552             {
00553               Color4b cc(Color4b::White);
00554               cc[0] =  (unsigned char)atoi( tokens[vert_per_face+1].c_str() );
00555               cc[1] =  (unsigned char)atoi( tokens[vert_per_face+2].c_str() );
00556               cc[2] =  (unsigned char)atoi( tokens[vert_per_face+3].c_str() );
00557               for ( ; f0<=f; f0++)
00558                 mesh.face[f0].C()=cc;
00559             }
00560             else
00561             {
00562               float color[3];
00563               color[0] = (float) atof( tokens[vert_per_face+1].c_str() );
00564               color[1] = (float) atof( tokens[vert_per_face+2].c_str() );
00565               color[2] = (float) atof( tokens[vert_per_face+3].c_str() );
00566               for ( ; f0<=f; f0++)
00567                 mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], 1.0f));
00568             }
00569             break;
00570           }
00571           case 4:
00572           {
00573             if (tokens[vert_per_face+1].find('.')==std::string::npos) // if it is a float there is a dot
00574             {
00575               Color4b cc;
00576               cc[0] = (unsigned char) atoi(tokens[vert_per_face+1].c_str());
00577               cc[1] = (unsigned char) atoi(tokens[vert_per_face+2].c_str());
00578               cc[2] = (unsigned char) atoi(tokens[vert_per_face+3].c_str());
00579               cc[3] = (unsigned char) atoi(tokens[vert_per_face+4].c_str());
00580               for ( ; f0<=f; f0++)
00581                 mesh.face[f0].C()=cc;
00582             }
00583             else
00584             {
00585               float color[4];
00586               color[0] = float( atof(tokens[vert_per_face+1].c_str()) );
00587               color[1] = float( atof(tokens[vert_per_face+2].c_str()) );
00588               color[2] = float( atof(tokens[vert_per_face+3].c_str()) );
00589               color[3] = float( atof(tokens[vert_per_face+4].c_str()) );
00590               for ( ; f0<=f; f0++)
00591                 mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], color[3]));
00592             }
00593             break;
00594           }
00595           } //end switch
00596         } // end if (isColorDefined)
00597       } // end of for f=...
00598     }
00599     return NoError;
00600 
00601   } // end Open
00602 
00603 protected:
00604 
00610   inline static void TokenizeNextLine(std::istream &stream, std::vector< std::string > &tokens)
00611   {
00612     std::string line;
00613     do
00614       std::getline(stream, line, '\n');
00615     while ((line[0] == '#' || line.length()==0 || line[0]=='\r' ) && (!stream.eof()));
00616 
00617     size_t from = 0;
00618     size_t to = 0;
00619     size_t length = line.size();
00620     tokens.clear();
00621     do
00622     {
00623       while (from!=length && (line[from]==' ' || line[from] == '\t'  || line[from] == '\r'))
00624         from++;
00625       if(from!=length)
00626       {
00627         to = from+1;
00628         while ( to!=length && (((line[to]!=' ') && (line[to] != '\t'))  || (line[to] == '\r')))
00629           to++;
00630         tokens.push_back(line.substr(from, to-from).c_str());
00631         from = to;
00632       }
00633     }
00634     while (from<length);
00635   } // end Tokenize
00636 
00642   static const vcg::Color4f ColorMap(int i)
00643   {
00644     static const float colorMap[148][4] =
00645     {
00646       { 1.0f,    1.0f,   1.0f,   1.0f    },
00647       { 1.0f,    1.0f,   1.0f,   1.0f    },
00648       { 1.0f,    1.0f,   1.0f,   1.0f    },
00649       { 1.0f,    1.0f,   1.0f,   1.0f    },
00650       { 1.0f,    1.0f,   1.0f,   1.0f    },
00651       { 1.0f,    1.0f,   1.0f,   1.0f    },
00652       { 0.7f,    0.7f,   0.7f,   0.7f    },
00653       { 0.2f,    0.2f,   0.2f,   0.2f    },
00654       { 0.9f,    0.9f,   0.9f,   0.9f    },
00655       { 0.1f,    0.1f,   0.1f,   0.1f    },
00656       { 0.1f,    0.1f,   0.1f,   0.1f    },
00657       { 0.8f,    0.8f,   0.8f,   0.8f    },
00658       { 0.7f,    0.7f,   0.7f,   0.7f    },
00659       { 0.7f,    0.7f,   0.7f,   0.7f    },
00660       { 0.0f,    0.0f,   0.0f,   0.0f    },
00661       { 0.9f,    0.9f,   0.9f,   0.9f    },
00662       { 0.2f,    0.2f,   0.2f,   0.2f    },
00663       { 0.0f,    0.0f,   0.0f,   0.0f    },
00664       { 0.75f, 0.75f,    0.75f,  0.75f },
00665       { 0.8f,    0.8f,   0.8f,   0.8f    },
00666       { 0.8f,    0.8f,   0.8f,   0.8f    },
00667       { 0.0f,    0.0f,   0.0f,   0.0f    },
00668       { 0.0f,    0.0f,   0.0f,   0.0f    },
00669       { 0.0f,    0.0f,   0.0f,   0.0f    },
00670       { 0.0f,    0.0f,   0.0f,   0.0f    },
00671       { 0.4f,    0.4f,   0.4f,   0.4f    },
00672       { 0.4f,    0.4f,   0.4f,   0.4f    },
00673       { 0.8f,    0.8f,   0.8f,   0.8f    },
00674       { 0.8f,    0.8f,   0.8f,   0.8f    },
00675       { 0.7f,    0.7f,   0.7f,   0.7f    },
00676       { 0.7f,    0.7f,   0.7f,   0.7f    },
00677       { 0.7f,    0.7f,   0.7f,   0.7f    },
00678       { 0.7f,    0.7f,   0.7f,   0.7f    },
00679       { 0.0f,    0.0f,   0.0f,   0.0f    },
00680       { 0.9f,    0.9f,   0.9f,   0.9f    },
00681       { 0.0f,    0.0f,   0.0f,   0.0f    },
00682       { 0.0f,    0.0f,   0.0f,   0.0f    },
00683       { 0.75f, 0.75f,    0.75f,  0.75f },
00684       { 0.8f,    0.8f,   0.8f,   0.8f    },
00685       { 0.4f,    0.4f,   0.4f,   0.4f    },
00686       { 0.0f,    0.0f,   0.0f,   0.0f    },
00687       { 0.0f,    0.0f,   0.0f,   0.0f    },
00688       { 0.4f,    0.4f,   0.4f,   0.4f    },
00689       { 0.8f,    0.8f,   0.8f,   0.8f    },
00690       { 0.7f,    0.7f,   0.7f,   0.7f    },
00691       { 0.7f,    0.7f,   0.7f,   0.7f    },
00692       { 0.0f,    0.0f,   0.0f,   0.0f    },
00693       { 0.9f,    0.9f,   0.9f,   0.9f    },
00694       { 0.0f,    0.0f,   0.0f,   0.0f    },
00695       { 0.0f,    0.0f,   0.0f,   0.0f    },
00696       { 0.75f, 0.75f,    0.75f,  0.75f },
00697       { 0.8f,    0.8f,   0.8f,   0.8f    },
00698       { 0.4f,    0.4f,   0.4f,   0.4f    },
00699       { 0.0f,    0.0f,   0.0f,   0.0f    },
00700       { 0.0f,    0.0f,   0.0f,   0.0f    },
00701       { 0.4f,    0.4f,   0.4f,   0.4f    },
00702       { 0.8f,    0.8f,   0.8f,   0.8f    },
00703       { 0.7f,    0.7f,   0.7f,   0.7f    },
00704       { 0.7f,    0.7f,   0.7f,   0.7f    },
00705       { 0.0f,    0.0f,   0.0f,   0.0f    },
00706       { 0.9f,    0.9f,   0.9f,   0.9f    },
00707       { 0.0f,    0.0f,   0.0f,   0.0f    },
00708       { 0.0f,    0.0f,   0.0f,   0.0f    },
00709       { 0.75f, 0.75f,    0.75f,  0.75f },
00710       { 0.8f,    0.8f,   0.8f,   0.8f    },
00711       { 0.4f,    0.4f,   0.4f,   0.4f    },
00712       { 0.0f,    0.0f,   0.0f,   0.0f    },
00713       { 0.0f,    0.0f,   0.0f,   0.0f    },
00714       { 0.4f,    0.4f,   0.4f,   0.4f    },
00715       { 0.8f,    0.8f,   0.8f,   0.8f    },
00716       { 1.0f,    1.0f,   1.0f,   1.0f    },
00717       { 1.0f,    1.0f,   1.0f,   1.0f    },
00718       { 1.0f,    1.0f,   1.0f,   1.0f    },
00719       { 1.0f,    1.0f,   1.0f,   1.0f    },
00720       { 1.0f,    1.0f,   1.0f,   1.0f    },
00721       { 1.0f,    1.0f,   1.0f,   1.0f    },
00722       { 0.05f, 0.05f,    0.05f,  0.05f },
00723       { 0.7f,    0.7f,   0.7f,   0.7f    },
00724       { 0.2f,    0.2f,   0.2f,   0.2f    },
00725       { 0.9f,    0.9f,   0.9f,   0.9f    },
00726       { 0.0f,    0.0f,   0.0f,   0.0f    },
00727       { 0.1f,    0.1f,   0.1f,   0.1f    },
00728       { 0.8f,    0.8f,   0.8f,   0.8f    },
00729       { 0.7f,    0.7f,   0.7f,   0.7f    },
00730       { 0.7f,    0.7f,   0.7f,   0.7f    },
00731       { 0.7f,    0.7f,   0.7f,   0.7f    },
00732       { 0.7f,    0.7f,   0.7f,   0.7f    },
00733       { 0.0f,    0.0f,   0.0f,   0.0f    },
00734       { 0.0f,    0.0f,   0.0f,   0.0f    },
00735       { 0.9f,    0.9f,   0.9f,   0.9f    },
00736       { 0.9f,    0.9f,   0.9f,   0.9f    },
00737       { 0.0f,    0.0f,   0.0f,   0.0f    },
00738       { 0.0f,    0.0f,   0.0f,   0.0f    },
00739       { 0.0f,    0.0f,   0.0f,   0.0f    },
00740       { 0.0f,    0.0f,   0.0f,   0.0f    },
00741       { 0.75f, 0.75f,    0.75f,  0.75f },
00742       { 0.75f, 0.75f,    0.75f,  0.75f },
00743       { 0.8f,    0.8f,   0.8f,   0.8f    },
00744       { 0.8f,    0.8f,   0.8f,   0.8f    },
00745       { 0.0f,    0.0f,   0.0f,   0.0f    },
00746       { 0.0f,    0.0f,   0.0f,   0.0f    },
00747       { 0.0f,    0.0f,   0.0f,   0.0f    },
00748       { 0.0f,    0.0f,   0.0f,   0.0f    },
00749       { 0.4f,    0.4f,   0.4f,   0.4f    },
00750       { 0.4f,    0.4f,   0.4f,   0.4f    },
00751       { 0.8f,    0.8f,   0.8f,   0.8f    },
00752       { 0.8f,    0.8f,   0.8f,   0.8f    },
00753       { 0.7f,    0.7f,   0.7f,   0.7f    },
00754       { 0.7f,    0.7f,   0.7f,   0.7f    },
00755       { 0.7f,    0.7f,   0.7f,   0.7f    },
00756       { 0.7f,    0.7f,   0.7f,   0.7f    },
00757       { 0.0f,    0.0f,   0.0f,   0.0f    },
00758       { 0.9f,    0.9f,   0.9f,   0.9f    },
00759       { 0.0f,    0.0f,   0.0f,   0.0f    },
00760       { 0.0f,    0.0f,   0.0f,   0.0f    },
00761       { 0.75f, 0.75f,    0.75f,  0.75f },
00762       { 0.8f,    0.8f,   0.8f,   0.8f    },
00763       { 0.4f,    0.4f,   0.4f,   0.4f    },
00764       { 0.0f,    0.0f,   0.0f,   0.0f    },
00765       { 0.0f,    0.0f,   0.0f,   0.0f    },
00766       { 0.4f,    0.4f,   0.4f,   0.4f    },
00767       { 0.8f,    0.8f,   0.8f,   0.8f    },
00768       { 0.7f,    0.7f,   0.7f,   0.7f    },
00769       { 0.7f,    0.7f,   0.7f,   0.7f    },
00770       { 0.0f,    0.0f,   0.0f,   0.0f    },
00771       { 0.9f,    0.9f,   0.9f,   0.9f    },
00772       { 0.0f,    0.0f,   0.0f,   0.0f    },
00773       { 0.0f,    0.0f,   0.0f,   0.0f    },
00774       { 0.75f, 0.75f,    0.75f,  0.75f },
00775       { 0.8f,    0.8f,   0.8f,   0.8f    },
00776       { 0.4f,    0.4f,   0.4f,   0.4f    },
00777       { 0.0f,    0.0f,   0.0f,   0.0f    },
00778       { 0.0f,    0.0f,   0.0f,   0.0f    },
00779       { 0.4f,    0.4f,   0.4f,   0.4f    },
00780       { 0.8f,    0.8f,   0.8f,   0.8f    },
00781       { 0.7f,    0.7f,   0.7f,   0.7f    },
00782       { 0.7f,    0.7f,   0.7f,   0.7f    },
00783       { 0.0f,    0.0f,   0.0f,   0.0f    },
00784       { 0.9f,    0.9f,   0.9f,   0.9f    },
00785       { 0.0f,    0.0f,   0.0f,   0.0f    },
00786       { 0.0f,    0.0f,   0.0f,   0.0f    },
00787       { 0.75f, 0.75f,    0.75f,  0.75f },
00788       { 0.8f,    0.8f,   0.8f,   0.8f    },
00789       { 0.4f,    0.4f,   0.4f,   0.4f    },
00790       { 0.0f,    0.0f,   0.0f,   0.0f    },
00791       { 0.0f,    0.0f,   0.0f,   0.0f    },
00792       { 0.4f,    0.4f,   0.4f,   0.4f    },
00793       { 0.8f,    0.8f,   0.8f,   0.8f    }
00794     };
00795     return Color4f(colorMap[i][0], colorMap[i][1], colorMap[i][2], colorMap[i][3]);
00796   }
00797 };
00798 // /*! @} */
00799 } //namespace io
00800 }//namespace tri
00801 } // namespace vcg
00802 
00803 #endif //__VCGLIB_IMPORT_OFF


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