00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00086
00087 fgets(buf, sizeof(buf), file);
00088 break;
00089 case 'v':
00090
00091 switch (buf[1])
00092 {
00093 case '\0':
00094
00095
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
00102
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
00109
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
00125
00126 std::string mtlfile = sofa::helper::system::SetDirectory::GetRelativeFromFile(buf, filename);
00127
00128
00129
00130 readMTL(mtlfile.c_str());
00131 }
00132 break;
00133 case 'u':
00134 {
00135
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
00145 (*it).activated = true;
00146 material = *it;
00147 }
00148 }
00149 }
00150 break;
00151 case 'g':
00152
00153
00154 fgets(buf, sizeof(buf), file);
00155 sscanf(buf, "%s", buf);
00156 break;
00157 case 'l':
00158 case 'f':
00159
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;
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
00196 fgets(buf, sizeof(buf), file);
00197 break;
00198 }
00199 }
00200
00201
00202
00203
00204
00205
00206 if (vertices.size()>0)
00207 {
00208
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
00224 }
00225
00226 }
00227
00228
00229
00230
00231
00232
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);
00241 else
00242 {
00243
00244 while (fscanf(file, "%s", buf) != EOF)
00245 {
00246
00247 switch (buf[0])
00248 {
00249 case '#':
00250
00251
00252 fgets(buf, sizeof(buf), file);
00253 break;
00254 case 'n':
00255
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
00278
00279
00280 mat->useShininess = true;
00281 break;
00282 default:
00283
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
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
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
00304 break;
00305 default:
00306
00307 fgets(buf, sizeof(buf), file);
00308 break;
00309 }
00310 break;
00311 case 'd':
00312 case 'T':
00313
00314 fscanf(file, "%f", &mat->diffuse[3]);
00315 break;
00316 default:
00317
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 }
00334
00335 }
00336
00337 }
00338