19 #include <boost/filesystem.hpp>
28 using namespace StrUtils;
29 using namespace FileUtils;
34 template<
typename MaterialType >
37 std::vector< MaterialType > &materials)
40 std::ofstream mtl_file(mtl_file_name, std::ios::out | std::ios::trunc);
41 if(!mtl_file.is_open())
42 throw std::runtime_error(
"write_MTL_file(): failed to create MTL file.");
45 if(parent_directory.empty())
46 parent_directory =
".";
47 const std::string texture_filepath_base = parent_directory +
'/';
50 mtl_file <<
"# MTL File produced by MEPP2" << std::endl;
51 for(
auto &material : materials)
53 mtl_file <<
"newmtl " << material.name << std::endl;
56 mtl_file <<
" Kd " << material.diffuse_red_component <<
' '
57 << material.diffuse_green_component <<
' '
58 << material.diffuse_blue_component << std::endl;
62 mtl_file <<
" Pm " << material.metallic_factor << std::endl;
63 mtl_file <<
" Pr " << material.roughness_factor << std::endl;
67 mtl_file <<
" Ka " << material.ambient_red_component <<
' '
68 << material.ambient_green_component <<
' '
69 << material.ambient_blue_component << std::endl;
70 mtl_file <<
" Ks " << material.specular_red_component <<
' '
71 << material.specular_green_component <<
' '
72 << material.specular_blue_component << std::endl;
73 mtl_file <<
" Ke " << material.emissive_red_component <<
' '
74 << material.emissive_green_component <<
' '
75 << material.emissive_blue_component << std::endl;
76 mtl_file <<
" d " << material.transparency << std::endl;
80 if(!material.diffuse_texture_filename.empty())
82 const std::string texture_filename =
84 mtl_file <<
" map_Kd " << texture_filename << std::endl;
88 *(material.images.at(material.diffuse_texture_filename));
89 img.save((texture_filepath_base + texture_filename).c_str());
93 if(!material.ambient_texture_filename.empty())
95 const std::string texture_filename =
97 mtl_file <<
" map_Ka " << texture_filename << std::endl;
101 *(material.images.at(material.ambient_texture_filename));
102 img.save((texture_filepath_base + texture_filename).c_str());
106 if(!material.normal_map_filename.empty())
108 const std::string texture_filename =
115 mtl_file << texture_filename << std::endl;
119 *(material.images.at(material.normal_map_filename));
120 img.save((texture_filepath_base + texture_filename).c_str());
126 if(!material.metallic_map_filename.empty())
128 const std::string texture_filename =
130 mtl_file <<
" map_Pm " << texture_filename << std::endl;
134 *(material.images.at(material.metallic_map_filename));
135 img.save((texture_filepath_base + texture_filename).c_str());
139 if(!material.roughness_map_filename.empty())
141 const std::string texture_filename =
143 mtl_file <<
" map_Pr " << texture_filename << std::endl;
147 *(material.images.at(material.roughness_map_filename));
148 img.save((texture_filepath_base + texture_filename).c_str());
154 if(!material.specular_texture_filename.empty())
156 const std::string texture_filename =
158 mtl_file <<
" map_Ks " << texture_filename << std::endl;
162 *(material.images.at(material.specular_texture_filename));
163 img.save((texture_filepath_base + texture_filename).c_str());
167 if(!material.transparency_texture_filename.empty())
169 const std::string texture_filename =
171 mtl_file <<
" map_d " << texture_filename << std::endl;
175 *(material.images.at(material.transparency_texture_filename));
176 img.save((texture_filepath_base + texture_filename).c_str());
180 mtl_file << std::endl;
189 template<
typename CoordType,
197 std::vector< std::vector< CoordType > > &points_coords,
198 std::vector< std::vector< CoordNType > > &normals_coords,
199 std::vector< std::vector< CoordTType > > &texture_coords,
200 std::vector< std::vector< CoordCType > > &vertex_color_coords,
201 std::vector< std::vector< IndexType > > &face_indices,
202 std::vector< std::vector< IndexType > > &texture_face_indices,
203 std::vector< std::vector< IndexType > > &normal_face_indices,
204 std::vector< MaterialType > &materials,
207 size_t nb_points = points_coords.size(), nb_normals = normals_coords.size(),
208 nb_tex_coords = texture_coords.size(),
209 nb_point_color = vertex_color_coords.size(),
210 nb_faces = face_indices.size(),
211 nb_texture_ind = texture_face_indices.size(),
212 nb_normal_ind = normal_face_indices.size(),
214 nb_materials = materials.size();
216 bool use_normal = (nb_normals != 0), use_texture = (nb_tex_coords != 0),
217 use_color = (nb_point_color != 0),
218 use_face_material = (nb_face_material != 0),
219 use_materials = (nb_materials != 0);
221 if((nb_point_color != nb_points) && (nb_point_color != 0))
222 throw std::invalid_argument(
223 "Writer::write_obj_file -> invalid number of vertex colors.");
225 if((nb_texture_ind != nb_faces) && (nb_texture_ind != 0))
226 throw std::invalid_argument(
227 "Writer::write_obj_file -> invalid number of texture indices.");
229 if((nb_normal_ind != nb_faces) && (nb_normal_ind != 0))
230 throw std::invalid_argument(
231 "Writer::write_obj_file -> invalid number of normal indices.");
233 if((nb_face_material != nb_faces) && (nb_face_material != 0))
234 throw std::invalid_argument(
235 "Writer::write_obj_file -> invalid number of face materials.");
239 std::string mtl_file_name;
244 if(parent_directory.empty())
245 parent_directory =
".";
247 std::string mtl_file_path = parent_directory +
"/" + mtl_file_name;
253 std::ofstream file(file_path, std::ios::out | std::ios::trunc);
257 file <<
"# OBJ File produced by MEPP2" << std::endl
258 <<
"# The M2Disco Framework" << std::endl
260 file <<
"# Mesh with :" << std::endl;
261 file <<
"# \t" << nb_points <<
" vertex positions" << std::endl;
262 file <<
"# \t" << nb_faces <<
" faces" << std::endl;
263 file <<
"# \t" << nb_tex_coords <<
" UV coordinates" << std::endl;
264 file <<
"# \t" << nb_normals <<
" vertex normals" << std::endl << std::endl;
270 file <<
"mtllib " << mtl_file_name << std::endl;
274 typename std::vector< std::vector< CoordCType > >::const_iterator it_c =
275 vertex_color_coords.cbegin();
276 for(
typename std::vector< std::vector< CoordType > >::const_iterator it_p =
277 points_coords.cbegin();
278 it_p != points_coords.cend();
282 for(
typename std::vector< CoordType >::const_iterator it_pc =
284 it_pc != it_p->cend();
286 file << *it_pc <<
" ";
290 for(
typename std::vector< CoordCType >::const_iterator it_cc =
292 it_cc != it_c->cend();
294 file << *it_cc <<
" ";
304 for(
typename std::vector< std::vector< CoordNType > >::const_iterator it_n =
305 normals_coords.cbegin();
306 it_n != normals_coords.cend();
310 for(
typename std::vector< CoordNType >::const_iterator it_nc =
312 it_nc != it_n->cend();
314 file << *it_nc <<
" ";
319 for(
typename std::vector< std::vector< CoordTType > >::const_iterator it_t =
320 texture_coords.cbegin();
321 it_t != texture_coords.cend();
325 for(
typename std::vector< CoordTType >::const_iterator it_tc =
327 it_tc != it_t->end();
329 file << *it_tc <<
" ";
334 IndexType current_material_id = -1;
335 std::string current_material_name;
336 for(
unsigned int no_face = 0; no_face < nb_faces; ++no_face)
339 if(use_face_material &&
face_material[no_face] != current_material_id)
342 file <<
"usemtl " << materials[current_material_id].name << std::endl;
347 for(
unsigned int no_vertex = 0; no_vertex < face_indices[no_face].size();
350 file << (face_indices[no_face][no_vertex] +
353 if(use_texture || use_normal)
357 file << (texture_face_indices[no_face][no_vertex] + 1);
360 file <<
"/" << (normal_face_indices[no_face][no_vertex] + 1);
371 throw std::runtime_error(
372 "Writer::write_obj_file -> output file failed to open.");