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++)