MeshOBJ.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include <sofa/helper/io/MeshOBJ.h>
00028 #include <sofa/helper/system/FileRepository.h>
00029 #include <sofa/helper/system/SetDirectory.h>
00030 #include <stdlib.h>
00031 #include <iostream>
00032 #include <stdio.h>
00033 #include <string.h>
00034 
00035 namespace sofa
00036 {
00037 
00038 namespace helper
00039 {
00040 
00041 namespace io
00042 {
00043 
00044 using namespace sofa::defaulttype;
00045 
00046 SOFA_DECL_CLASS(MeshOBJ)
00047 
00048 Creator<Mesh::FactoryMesh,MeshOBJ> MeshOBJClass("obj");
00049 
00050 void MeshOBJ::init (std::string filename)
00051 {
00052     if (!sofa::helper::system::DataRepository.findFile(filename))
00053     {
00054     std::cerr << "File " << filename << " not found " << std::endl;
00055     return;
00056     }
00057     FILE *f = fopen(filename.c_str(), "r");
00058     if (f)
00059     {
00060         readOBJ (f,filename.c_str());
00061         fclose(f);
00062     }
00063     else
00064         std::cerr << "File " << filename << " not found " << std::endl;
00065 }
00066 
00067 void MeshOBJ::readOBJ (FILE* file, const char* filename)
00068 {
00069     vector< vector<int> > vertNormTexIndices;
00070     vector<int>vIndices, nIndices, tIndices;
00071     int vtn[3];
00072     char buf[128], matName[1024];
00073     Vec3d result;
00074     Vec3d texCoord;
00075     Vec3d normal;
00076     const char *token;
00077 
00078     std::string face, tmp;
00079 
00080     while (fscanf(file, "%s", buf) != EOF)
00081     {
00082         switch (buf[0])
00083         {
00084             case '#':
00085                 /* comment */
00086                 /* eat up rest of line */
00087                 fgets(buf, sizeof(buf), file);
00088                 break;
00089             case 'v':
00090                 /* v, vn, vt */
00091                 switch (buf[1])
00092                 {
00093                     case '\0':
00094                         /* vertex */
00095                         /* eat up rest of line */
00096                         fgets(buf, sizeof(buf), file);
00097                         sscanf(buf, "%lf %lf %lf", &result[0], &result[1], &result[2]);
00098                         vertices.push_back(Vector3(result[0],result[1], result[2]));
00099                         break;
00100                     case 'n':
00101                         /* normal */
00102                         /* eat up rest of line */
00103                         fgets(buf, sizeof(buf), file);
00104                         sscanf(buf, "%lf %lf %lf", &result[0], &result[1], &result[2]);
00105                         normals.push_back(Vector3(result[0],result[1], result[2]));
00106                         break;
00107                     case 't':
00108                         /* texcoord */
00109                         /* eat up rest of line */
00110                         fgets(buf, sizeof(buf), file);
00111                         sscanf (buf, "%lf %lf", &result[0], &result[1]);
00112                         texCoords.push_back(Vector3(result[0],result[1], result[2]));                       
00113                         break;
00114                     default:
00115                         printf("readObj : Unknown token \"%s\".\n", buf);
00116                         exit(1);
00117                         break;
00118                 }
00119                 break;
00120             case 'm':
00121                 {
00122                     fgets(buf, sizeof(buf), file);
00123                     sscanf(buf, "%s %s", buf, buf);
00124                     //mtllibname = strdup(buf);
00125                     //fscanf(file, "%s", buf);
00126                     std::string mtlfile = sofa::helper::system::SetDirectory::GetRelativeFromFile(buf, filename);
00127 //std::cerr << "Buf = " << buf << std::endl;
00128 //std::cerr << "Filename = " << filename << std::endl;
00129 
00130                     readMTL(mtlfile.c_str());
00131                 }
00132                 break;
00133             case 'u':
00134                 {
00135                     /* eat up rest of line */
00136                     fgets(buf, sizeof(buf), file);
00137                     sscanf(buf, "%s", matName);
00138                     vector<Material>::iterator it = materials.begin();
00139                     vector<Material>::iterator itEnd = materials.end();
00140                     for (; it != itEnd; it++)
00141                     {
00142                         if (it->name == matName)
00143                         {
00144 //                              std::cout << "Using material "<<it->name<<std::endl;
00145                             (*it).activated = true;
00146                             material = *it;
00147                         }
00148                     }
00149                 }
00150                 break;
00151             case 'g':
00152                 /* group */
00153                 /* eat up rest of line */
00154                 fgets(buf, sizeof(buf), file);
00155                 sscanf(buf, "%s", buf);
00156                 break;
00157             case 'l': // for now we consider a line as a 2-vertices face
00158             case 'f':
00159                 // face 
00160                 fgets(buf, sizeof(buf), file);
00161                 token = strtok(buf, " ");
00162                 
00163                 vIndices.clear();
00164                 nIndices.clear();
00165                 tIndices.clear();
00166                 vertNormTexIndices.clear();
00167                 
00168                 while(token!=NULL && token[0]>='0' && token[0]<='9')
00169                 {
00170                     face = token;
00171                     for (int j = 0; j < 3; j++)
00172                     {
00173                         vtn[j] = 0;
00174                         std::string::size_type pos = face.find('/');
00175                         tmp = face.substr(0, pos);
00176                         if (tmp != "")
00177                             vtn[j] = atoi(tmp.c_str()) - 1; // -1 because the numerotation begins at 1 and a vector begins at 0
00178                         if (pos == std::string::npos)
00179                             face = "";
00180                         else
00181                             face = face.substr(pos + 1);
00182                     }
00183                     vIndices.push_back(vtn[0]);
00184                     nIndices.push_back(vtn[1]);
00185                     tIndices.push_back(vtn[2]);
00186                     token = strtok(NULL, " ");
00187                 }
00188                 vertNormTexIndices.push_back (vIndices);
00189                 vertNormTexIndices.push_back (nIndices);
00190                 vertNormTexIndices.push_back (tIndices);
00191                 facets.push_back(vertNormTexIndices);
00192                 break;
00193 
00194             default:
00195                 // eat up rest of line 
00196                 fgets(buf, sizeof(buf), file);
00197                 break;
00198         }
00199     }
00200 
00201     // announce the model statistics 
00202 //  std::cout << " Vertices: " << vertices.size() << std::endl;
00203 //  std::cout << " Normals: " << normals.size() << std::endl;
00204 //  std::cout << " Texcoords: " << texCoords.size() << std::endl;
00205 //  std::cout << " Triangles: " << facets.size() << std::endl;
00206     if (vertices.size()>0)
00207     {
00208         // compute bbox
00209         Vector3 minBB = vertices[0];
00210         Vector3 maxBB = vertices[0];
00211         for (unsigned int i=1; i<vertices.size();i++)
00212         {
00213             Vector3 p = vertices[i];
00214             for (int c=0;c<3;c++)
00215             {
00216                 if (minBB[c] > p[c])
00217                     minBB[c] = p[c];
00218                 if (maxBB[c] < p[c])
00219                     maxBB[c] = p[c];
00220             }
00221         }
00222         
00223 //      std::cout << "BBox: <"<<minBB[0]<<','<<minBB[1]<<','<<minBB[2]<<">-<"<<maxBB[0]<<','<<maxBB[1]<<','<<maxBB[2]<<">\n";
00224     }
00225 
00226 }
00227 
00228 // -----------------------------------------------------
00229 // readMTL: read a wavefront material library file
00230 //
00231 //    model - properly initialized GLMmodel structure
00232 //    name  - name of the material library
00233 // -----------------------------------------------------
00234 void MeshOBJ::readMTL(const char* filename)
00235 {
00236     FILE* file;
00237     char buf[128];
00238     file = fopen(filename, "r");
00239     Material *mat = NULL;
00240     if (!file);//std::cerr << "readMTL() failed: can't open material file " << filename << std::endl;
00241     else
00242     {
00243         /* now, read in the data */
00244         while (fscanf(file, "%s", buf) != EOF)
00245         {
00246             
00247             switch (buf[0])
00248             {
00249                 case '#':
00250                     /* comment */
00251                     /* eat up rest of line */
00252                     fgets(buf, sizeof(buf), file);
00253                     break;
00254                 case 'n':
00255                     /* newmtl */
00256                     if (mat != NULL) 
00257                     {
00258                         materials.push_back(*mat);
00259                         delete mat;
00260                         mat = NULL;
00261                     }
00262                     mat = new Material();
00263                     fgets(buf, sizeof(buf), file);
00264                     sscanf(buf, "%s %s", buf, buf);
00265                     mat->name = buf;
00266                     break;
00267                 case 'N':
00268                     switch (buf[1]) {
00269                         case 'i':
00270                         {
00271                             float optical_density;
00272                             fscanf(file, "%f", &optical_density);
00273                             break;
00274                         }
00275                         case 's':
00276                             fscanf(file, "%f", &mat->shininess);
00277                             // wavefront shininess is from [0, 1000], so scale for OpenGL
00278                             //mat->shininess /= 1000.0;
00279                             //mat->shininess *= 128.0;
00280                             mat->useShininess = true;
00281                             break;
00282                         default:
00283                             /* eat up rest of line */
00284                             fgets(buf, sizeof(buf), file);
00285                             break;
00286                     }
00287                     break;
00288                 case 'K':
00289                     switch (buf[1]) {
00290                         case 'd':
00291                             fscanf(file, "%f %f %f", &mat->diffuse[0], &mat->diffuse[1], &mat->diffuse[2]);
00292                             mat->useDiffuse = true;
00293                             /*std::cout << mat->name << " diffuse = "<<mat->diffuse[0]<<' '<<mat->diffuse[1]<<'*/ /*'<<mat->diffuse[2]<<std::endl;*/
00294                             break;
00295                         case 's':
00296                             fscanf(file, "%f %f %f", &mat->specular[0], &mat->specular[1], &mat->specular[2]);
00297                             mat->useSpecular = true;
00298                             /*std::cout << mat->name << " specular = "<<mat->specular[0]<<' '<<mat->specular[1]<<'*/ /*'<<mat->specular[2]<<std::endl;*/
00299                             break;
00300                         case 'a':
00301                             fscanf(file, "%f %f %f", &mat->ambient[0], &mat->ambient[1], &mat->ambient[2]);
00302                             mat->useAmbient = true;
00303                             /*std::cout << mat->name << " ambient = "<<mat->ambient[0]<<' '<<mat->ambient[1]<<'*/ /*'<<mat->ambient[2]<<std::endl;*/
00304                             break;
00305                         default:
00306                             /* eat up rest of line */
00307                             fgets(buf, sizeof(buf), file);
00308                             break;
00309                     }
00310                     break;
00311                 case 'd':
00312                 case 'T':
00313                     // transparency value
00314                     fscanf(file, "%f", &mat->diffuse[3]);
00315                     break;
00316                 default:
00317                     /* eat up rest of line */
00318                     fgets(buf, sizeof(buf), file);
00319                     break;
00320             }
00321             
00322         }
00323         fclose(file);
00324     }
00325     if (mat != NULL) 
00326     {
00327         materials.push_back(*mat);
00328         delete mat;
00329         mat = NULL;
00330     }
00331 }
00332 
00333 } // namespace io
00334 
00335 } // namespace helper
00336 
00337 } // namespace sofa
00338 

Generated on Sun Nov 23 02:29:30 2008 for Sofa by  doxygen 1.5.7.1