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;
173 boost::filesystem::path
p(filename);
175 ifstream in(filename.c_str());
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;
385 ofstream out(filename.c_str());
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++)
void saveTextures(std::vector< int32_t > *textureValue, textureArr textures, size_t numTextures)
pushes the given textures in a int32_t vector to store it in the draco structure
A material that stores information about color and texture of a cluster.
std::shared_ptr< MeshBuffer > MeshBufferPtr
boost::shared_array< unsigned int > uintArr
int m_index
Texture index.
void tokenize(const string &str, vector< string > &tokens, const string &delimiters=" ")
static Timestamp timestamp
A global time stamp object for program runtime measurement.
boost::optional< int > intOptional
boost::shared_array< unsigned char > ucharArr
Handle to access textures of the mesh.
static void saveTexture(const Texture &texture, std::string filename)
TODO.
boost::shared_array< unsigned int > indexArray
uintArr faceMaterialIndices
This class represents a texture.
boost::shared_array< float > floatArr
ModelPtr read(string filename)
Parse the given file and load supported elements.
std::shared_ptr< Model > ModelPtr
bool operator()(int i, int j)
void save(string filename)
Writes the mesh to an obj file.
boost::optional< Rgb8Color > m_color
Optional color.
static Texture readTexture(std::string filename)
Returns a new texture if the file contains readable image data or a null point if the file couldn't b...
void parseMtlFile(map< string, int > &matNames, vector< Material > &materials, vector< Texture > &textures, string mtlname)
boost::optional< TextureHandle > m_texture
Optional texture handle.
sort_indices(uintArr faceMaterialIndices)
static boost::shared_array< T > convert_vector_to_shared_array(std::vector< T > source)
Creates a shared array with the data from the given vector.
The MeshBuffer Mesh representation for I/O modules.