46 #include <boost/filesystem.hpp> 
   47 #include <boost/tuple/tuple.hpp> 
   64                       vector<string>& tokens,
 
   65                       const string& delimiters = 
" ")
 
   68     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
 
   70     string::size_type pos     = str.find_first_of(delimiters, lastPos);
 
   72     while (string::npos != pos || string::npos != lastPos)
 
   75         tokens.push_back(str.substr(lastPos, pos - lastPos));
 
   77         lastPos = str.find_first_not_of(delimiters, pos);
 
   79         pos = str.find_first_of(delimiters, lastPos);
 
   84         map<string, int>& matNames,
 
   85         vector<Material>& materials,
 
   86         vector<Texture>& textures,
 
   89     cout << 
"Parsing " << mtlname << endl;
 
   92     boost::filesystem::path 
p(mtlname);
 
   93     p = 
p.remove_filename();
 
   95     ifstream in(mtlname.c_str());
 
  102             in.getline(buffer, 1024);
 
  105             if(buffer[0] == 
'#') 
continue;
 
  107             stringstream ss(buffer);
 
  112             if(keyword == 
"newmtl")
 
  116                 map<string, int>::iterator it = matNames.find(matName);
 
  117                 if(it == matNames.end())
 
  120                     m.
m_color = boost::optional<Rgb8Color>({128, 128, 128});
 
  122                     materials.push_back(m);
 
  123                     matNames[matName] = matIndex;
 
  130                     cout << 
"ObjIO::parseMtlFile(): Warning: Duplicate material: " << matName << endl;
 
  133             else if(keyword == 
"Ka")
 
  137                 Material& current = materials.back();
 
  138                 current.
m_color = boost::optional<Rgb8Color>({
 
  139                     static_cast<unsigned char>(r * 255 + 0.5),
 
  140                     static_cast<unsigned char>(g * 255 + 0.5),
 
  141                     static_cast<unsigned char>(b * 255 + 0.5)
 
  144             else if(keyword == 
"map_Kd")
 
  150                 boost::filesystem::path tex_file = 
p / texname;
 
  153                 unsigned int tex_idx = textures.size();
 
  155                 textures.push_back(std::move(texture));
 
  166         cout << 
"ObjIO::parseMtlFile(): Error opening '" << mtlname << 
"'." << endl;
 
  179     vector<float>         vertices;
 
  180     vector<float>         normals;
 
  181     vector<unsigned char> 
colors;
 
  182     vector<float>         texcoords;
 
  183     vector<uint>          faceMaterials;
 
  185     vector<Material>&     materials = 
mesh->getMaterials();
 
  186     vector<Texture>&      textures = 
mesh->getTextures();
 
  188     map<string, int> matNames;
 
  197             in.getline(buffer, 1024);
 
  200             if(buffer[0] == 
'#') 
continue;
 
  202             stringstream ss(buffer);
 
  210                 vertices.push_back(x);
 
  211                 vertices.push_back(y);
 
  212                 vertices.push_back(z);
 
  215                 bool colors_exist = 
static_cast<bool>(ss >> r);
 
  220                     colors.push_back(
static_cast<unsigned char>(r*255.0 + 0.5));
 
  221                     colors.push_back(
static_cast<unsigned char>(g*255.0 + 0.5));
 
  222                     colors.push_back(
static_cast<unsigned char>(b*255.0 + 0.5));
 
  225             else if(keyword == 
"vt")
 
  228                 texcoords.push_back(x);
 
  229                 texcoords.push_back(1.0 - y);
 
  233             else if(keyword == 
"vn")
 
  236                 normals.push_back(x);
 
  237                 normals.push_back(y);
 
  238                 normals.push_back(z);
 
  240             else if(keyword == 
"f")
 
  242                 vector<string> tokens;
 
  245                 if(tokens.size() < 4)
 
  248                 vector<string> tokens2;
 
  250                 int a = atoi(tokens2.at(0).c_str());
 
  254                 int b = atoi(tokens2.at(0).c_str());
 
  258                 int c = atoi(tokens2.at(0).c_str());
 
  261                 faces.push_back(a - 1);
 
  262                 faces.push_back(b - 1);
 
  263                 faces.push_back(c - 1);
 
  266                 faceMaterials.push_back(currentMat);
 
  268             else if(keyword == 
"usemtl")
 
  273                 map<string, int>::iterator it = matNames.find(mtlname);
 
  274                 if(it == matNames.end())
 
  276                     cout << 
"ObjIO:read(): Warning material '" << mtlname << 
"' is undefined." << endl;
 
  280                     currentMat = it->second;
 
  283             else if(keyword == 
"mtllib")
 
  286                 p = 
p.remove_filename();
 
  294                 string mtl_path = 
p.string();
 
  295                 parseMtlFile(matNames, materials, textures, mtl_path);
 
  302         cout << 
timestamp << 
"ObjIO::read(): Unable to open file'" << 
filename << 
"'." << endl;
 
  308     if(faceMaterials.size() == faces.size() / 3)
 
  314         cout << 
"ObjIO::read(): Warning: Face material index buffer does not match face number." << endl;
 
  334      bool operator()(
int i, 
int j) { 
return faceMaterialIndices[i]<faceMaterialIndices[j]; }
 
  339     if (!m_model->m_mesh)
 
  341         std::cout << 
"ObjIO: Unable to save to file " << 
filename << 
". No mesh to save present." << std::endl;
 
  346     size_t lenVertices = m_model->m_mesh->numVertices();
 
  347     size_t lenNormals = lenVertices;
 
  348     size_t lenFaces = m_model->m_mesh->numFaces();
 
  349     size_t lenTextureCoordinates = lenVertices;
 
  350     size_t lenFaceMaterialIndices = lenFaces;
 
  351     size_t lenColors = lenVertices;
 
  352     floatArr vertices              = m_model->m_mesh->getVertices();
 
  353     floatArr normals               = m_model->m_mesh->getVertexNormals();
 
  354     floatArr textureCoordinates    = m_model->m_mesh->getTextureCoordinates();
 
  355     indexArray faceIndices         = m_model->m_mesh->getFaceIndices();
 
  356     vector<Material> &materials    = m_model->m_mesh->getMaterials();
 
  357     indexArray faceMaterialIndices = m_model->m_mesh->getFaceMaterialIndices();
 
  361     std::string textureImageExtension = 
".ppm";
 
  364     intOptional saveTexturesOpt = m_model->m_mesh->getIntAtomic(
"mesh_save_textures");
 
  365     if (saveTexturesOpt && (*saveTexturesOpt) != 0)
 
  370     intOptional textureImageExtensionOpt = m_model->m_mesh->getIntAtomic(
"mesh_texture_image_extension");
 
  373     if (textureImageExtensionOpt)
 
  375         switch (*textureImageExtensionOpt) {
 
  376             case 1: textureImageExtension = 
".jpg"; 
break;
 
  377             case 2: textureImageExtension = 
".png"; 
break;
 
  382     std::set<unsigned int> materialIndexSet;
 
  383     std::set<unsigned int> colorIndexSet;
 
  386     ofstream mtlFile(
"textures.mtl");
 
  390         out<<
"mtllib textures.mtl"<<endl;
 
  394             cerr << 
"Received no vertices to store. Aborting save operation." << endl;
 
  397         out << endl << endl << 
"##  Beginning of vertex definitions.\n";
 
  399         for( 
size_t i=0; i < lenVertices; ++i )
 
  401             out << 
"v " << vertices[i*3 + 0] << 
" " 
  402                     << vertices[i*3 + 1] << 
" " 
  403                     << vertices[i*3 + 2] << 
" ";
 
  405                         unsigned char r = 
colors[i*w_color + 0],
 
  406                                       g = 
colors[i*w_color + 1],
 
  407                                       b = 
colors[i*w_color + 2];
 
  409                         out << static_cast<float>(r)/255.0 << 
" " 
  410                         << 
static_cast<float>(g)/255.0 << 
" " 
  411                         << 
static_cast<float>(b)/255.0 ;
 
  419         if (m_model->m_mesh->hasVertexNormals())
 
  421             out << endl << endl << 
"##  Beginning of vertex normals.\n";
 
  422             for( 
size_t i=0; i < lenNormals; ++i )
 
  424                 out << 
"vn " << normals[i*3 + 0] << 
" " 
  425                         << normals[i*3 + 1] << 
" " 
  426                         << normals[i*3 + 2] << endl;
 
  430         out << endl << endl << 
"##  Beginning of vertexTextureCoordinates.\n";
 
  432         for( 
size_t i=0; i < lenTextureCoordinates; ++i )
 
  434             out << 
"vt " << textureCoordinates[i*2 + 0] << 
" " 
  435                     << 1.0 - textureCoordinates[i*2 + 1] << 
" " 
  440         out << endl << endl << 
"##  Beginning of faces.\n";
 
  473         std::vector<int> color_indices, texture_indices;
 
  476         for(
size_t i = 0; i< lenFaceMaterialIndices; ++i)
 
  478             Material &m = materials[faceMaterialIndices[i]];
 
  481                 texture_indices.push_back(i);
 
  483                 color_indices.push_back(i);
 
  488         std::sort(color_indices.begin(),color_indices.end(),
sort_indices(faceMaterialIndices));
 
  489         std::sort(texture_indices.begin(),texture_indices.end(),
sort_indices(faceMaterialIndices));
 
  492         for(
size_t i = 0; i<color_indices.size() ; i++)
 
  494             unsigned int first = faceMaterialIndices[color_indices[i]];
 
  495             unsigned int face_index=color_indices[i];
 
  497             if( i == 0 || 
first != faceMaterialIndices[color_indices[i-1]] )
 
  499                 out << 
"usemtl color_" << faceMaterialIndices[color_indices[i]] << endl;
 
  501                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  502                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  503                     << faceIndices[face_index * 3 + 0] + 1 << 
" " 
  504                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  505                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  506                     << faceIndices[face_index * 3 + 1] + 1 << 
" " 
  507                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  508                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  509                     << faceIndices[face_index * 3 + 2] + 1 << endl;
 
  511             }
else if( 
first == faceMaterialIndices[color_indices[i-1]] )
 
  514                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  515                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  516                     << faceIndices[face_index * 3 + 0] + 1 << 
" " 
  517                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  518                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  519                     << faceIndices[face_index * 3 + 1] + 1 << 
" " 
  520                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  521                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  522                     << faceIndices[face_index * 3 + 2] + 1 << endl;
 
  529         for(
size_t i = 0; i<texture_indices.size() ; i++)
 
  531             Material &
first = materials[faceMaterialIndices[texture_indices[i]]];
 
  532             size_t face_index=texture_indices[i];
 
  534             if(i==0 || 
first.m_texture != materials[faceMaterialIndices[texture_indices[i-1]]].m_texture )
 
  536                 out << 
"usemtl texture_" << 
first.m_texture->idx() << endl;
 
  539                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  540                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  541                     << faceIndices[face_index * 3 + 0] + 1 << 
" " 
  542                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  543                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  544                     << faceIndices[face_index * 3 + 1] + 1 << 
" " 
  545                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  546                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  547                     << faceIndices[face_index * 3 + 2] + 1 << endl;
 
  548             }
else if(
first.m_texture == materials[faceMaterialIndices[texture_indices[i-1]]].m_texture )
 
  551                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  552                     << faceIndices[face_index * 3 + 0] + 1 << 
"/" 
  553                     << faceIndices[face_index * 3 + 0] + 1 << 
" " 
  554                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  555                     << faceIndices[face_index * 3 + 1] + 1 << 
"/" 
  556                     << faceIndices[face_index * 3 + 1] + 1 << 
" " 
  557                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  558                     << faceIndices[face_index * 3 + 2] + 1 << 
"/" 
  559                     << faceIndices[face_index * 3 + 2] + 1 << endl;
 
  569         cerr << 
"no good. file! \n";
 
  577         for(
int i = 0; i < materials.size(); i++)
 
  582                 mtlFile << 
"newmtl color_" << i << endl;
 
  584                         << m.
m_color->at(0) / 255.0f << 
" " 
  585                         << m.
m_color->at(1) / 255.0f << 
" " 
  586                         << m.
m_color->at(2) / 255.0f << endl;
 
  588                         << m.
m_color->at(0) / 255.0f << 
" " 
  589                         << m.
m_color->at(1) / 255.0f << 
" " 
  590                         << m.
m_color->at(2) / 255.0f << endl << endl;
 
  594                 mtlFile << 
"newmtl texture_"      << m.
m_texture->idx() << endl;
 
  595                 mtlFile << 
"Ka 1.000 1.000 1.000" << endl;
 
  596                 mtlFile << 
"Kd 1.000 1.000 1.000" << endl;
 
  597                 mtlFile << 
"map_Kd texture_"      << m.
m_texture->idx()
 
  598                         << textureImageExtension << endl << endl;
 
  607         std::vector<Texture>& texts = m_model->m_mesh->getTextures();
 
  609         for (
size_t i = 0; i < texts.size(); i++)