45 #define FILEOBJPLUGIN_C 49 #include <OpenMesh/Core/Utils/color_cast.hh> 50 #include <OpenMesh/Core/Geometry/VectorT.hh> 55 template<
class MeshT >
58 bool optionFaceColors =
false;
59 bool optionFaceColorsOverride =
false;
60 bool optionColorAlpha =
false;
61 bool optionTextures =
false;
62 bool optionCopyTextures =
false;
63 bool optionCreateTexFolder =
false;
66 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0) {
68 optionColorAlpha = saveAlpha_->isChecked();
69 optionTextures = saveTextures_->isChecked();
70 optionCopyTextures = saveCopyTextures_->isChecked();
71 optionCreateTexFolder = saveCreateTexFolder_->isChecked();
75 std::fstream matStream( _filename.toStdString().c_str(), std::ios_base::out );
79 emit log(
LOGERR, tr(
"writeMaterial : cannot not open file %1").arg(_filename) );
90 typename MeshT::FaceIter f_it;
91 typename MeshT::FaceIter f_end = _mesh.faces_end();
94 for (f_it = _mesh.faces_begin(); f_it != f_end; ++f_it){
95 getMaterial(_mesh, *f_it, _objId);
100 Material& mat = (*it).second;
101 matStream <<
"newmtl " << mat <<
'\n';
102 matStream <<
"Ka 0.5000 0.5000 0.5000" <<
'\n';
104 matStream <<
"Kd " << c[0] <<
" " << c[1] <<
" " << c[2] <<
'\n';
105 if(optionColorAlpha) {
106 matStream <<
"Tr " << mat.Tr() <<
'\n';
108 matStream <<
"illum 1" <<
'\n';
111 if(optionTextures && mat.has_Texture()) {
112 if(optionCopyTextures) {
114 QFileInfo file(mat.map_Kd().c_str());
115 if(optionCreateTexFolder) {
116 QFileInfo materialFilename(_filename);
118 matStream <<
"map_Kd " << materialFilename.baseName().toStdString() <<
"_textures" << QDir::separator().toLatin1()
119 << file.fileName().toStdString() <<
'\n';
121 matStream <<
"map_Kd " << file.fileName().toStdString() <<
'\n';
125 matStream <<
"map_Kd " << mat.map_Kd() <<
'\n';
139 template<
class MeshT >
142 bool optionFaceColors =
false;
143 bool optionFaceColorsOverride =
false;
144 bool optionColorAlpha =
false;
146 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0) {
147 optionFaceColors = saveFaceColor_->isChecked();
148 optionFaceColorsOverride = saveFaceColorOverride_->isChecked();
149 optionColorAlpha = saveAlpha_->isChecked();
155 if ( optionFaceColors && !optionFaceColorsOverride ) {
159 if ( c[0] > 255.0 || c[1] > 255.0 || c[2] > 255.0 || c[0] < 0.0 || c[1] < 0.0 || c[2] < 0.0 || std::isnan(c[0]) || std::isnan(c[1]) || std::isnan(c[2]) ) {
177 if(!textureIndexPropFetched_) {
178 emit textureIndexPropertyName(_objId, textureIndexPropertyName_);
179 textureIndexPropFetched_ =
true;
184 if ( _mesh.get_property_handle(texture_index_property, textureIndexPropertyName_.toStdString()) ) {
185 texIndex = _mesh.property(texture_index_property, _fh);
186 }
else if ( _mesh.get_property_handle(texture_index_property,
"f:textureindex") ) {
187 texIndex = _mesh.property(texture_index_property, _fh);
188 }
else if(_mesh.has_face_texture_index()) {
189 texIndex = _mesh.texture_index(_fh);
192 emit getCurrentTexture(_objId, texName);
193 if(texName !=
"NONE")
194 emit textureIndex(texName, _objId, texIndex);
198 bool hasTexture =
false;
203 std::map<int,QString>::iterator it = texIndexFileMap_.find(texIndex);
205 if(it != texIndexFileMap_.end()) {
207 filename = (*it).second;
212 emit textureName(_objId, texIndex, texName);
214 if(texName !=
"NOT_FOUND") {
215 emit textureFilename( _objId, texName, filename );
217 texIndexFileMap_.insert(std::pair<int,QString>(texIndex, filename));
228 if(((*it).second).Kd() ==
ACG::Vec3f(c[0], c[1], c[2]) &&
229 ((optionColorAlpha && ((*it).second).Tr() == c[3]) || !optionColorAlpha))
233 QString mKd(((*it).second).map_Kd().c_str());
234 if((((*it).second).Kd() ==
ACG::Vec3f(c[0], c[1], c[2]) &&
235 ((optionColorAlpha && ((*it).second).Tr() == c[3]) || !optionColorAlpha)) &&
236 (filename == mKd && ((*it).second).map_Kd_index() == texIndex))
244 mat.set_Kd(c[0], c[1], c[2]);
246 if(optionColorAlpha) mat.set_Tr(c[3]);
250 mat.set_map_Kd(filename.toStdString(), texIndex);
252 materials_.insert(std::make_pair(QString(
"Material%1").arg(mat.material_number()).toStdString(), mat));
263 template<
class MeshT >
264 bool FileOBJPlugin::writeMesh(std::ostream& _out, QString _filename, MeshT& _mesh,
int _objId){
266 unsigned int i, nV, idx;
269 typename MeshT::VertexHandle vh;
270 bool useMaterial =
false;
273 bool optionFaceColors =
false;
274 bool optionVertexNormals =
false;
275 bool optionVertexTexCoords =
true;
276 bool optionTextures =
false;
277 bool optionCopyTextures =
false;
278 bool optionCreateTexFolder =
false;
280 QFileInfo fi(_filename);
283 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0) {
284 optionFaceColors = saveFaceColor_->isChecked();
285 optionVertexNormals = saveNormals_->isChecked();
286 optionVertexTexCoords = saveTexCoords_->isChecked();
287 optionTextures = saveTextures_->isChecked();
288 optionCopyTextures = saveCopyTextures_->isChecked();
289 optionCreateTexFolder = saveCreateTexFolder_->isChecked();
290 _out.precision(savePrecision_->value());
295 if ( optionFaceColors || optionTextures ){
297 QString matFile = fi.absolutePath() + QDir::separator() + fi.baseName() +
".mtl";
303 _out <<
"# " << _mesh.n_vertices() <<
" vertices, ";
304 _out << _mesh.n_faces() <<
" faces" <<
'\n';
307 if (useMaterial && optionFaceColors )
308 _out <<
"mtllib " << fi.baseName().toStdString() <<
".mtl" <<
'\n';
313 std::map<typename MeshT::VertexHandle, int> vtMapV;
317 for (i=0, nV=_mesh.n_vertices(); i<nV; ++i)
319 vh =
typename MeshT::VertexHandle(i);
321 n = _mesh.normal(vh);
323 if ( _mesh.has_vertex_texcoords2D() && !_mesh.has_halfedge_texcoords2D() )
324 t = _mesh.texcoord2D(vh);
327 _out <<
"v " << v[0] <<
" "<< v[1] <<
" "<< v[2] <<
'\n';
330 if ( optionVertexNormals)
331 _out <<
"vn " << n[0] <<
" "<< n[1] <<
" "<< n[2] <<
'\n';
334 if ( optionVertexTexCoords && _mesh.has_vertex_texcoords2D() && !_mesh.has_halfedge_texcoords2D()) {
335 _out <<
"vt " << t[0] <<
" "<< t[1] <<
'\n';
336 vtMapV.insert(std::pair<typename MeshT::VertexHandle, int>(vh, cf));
341 typename MeshT::FaceVertexIter fv_it;
342 typename MeshT::FaceHalfedgeIter fh_it;
343 typename MeshT::FaceIter f_it;
348 std::map<typename MeshT::HalfedgeHandle, int> vtMap;
351 if(optionVertexTexCoords && _mesh.has_halfedge_texcoords2D()) {
353 for (
auto f_it : _mesh.faces() ) {
354 for(fh_it=_mesh.fh_iter(f_it); fh_it.is_valid(); ++fh_it) {
356 _out <<
"vt " << t[0] <<
" " << t[1] <<
'\n';
357 vtMap.insert(std::pair<typename MeshT::HalfedgeHandle, int>(*fh_it, count));
366 bool vertexOnly = !(optionVertexTexCoords && _mesh.has_halfedge_texcoords2D())
367 && !(optionVertexTexCoords && !_mesh.has_halfedge_texcoords2D() && _mesh.has_vertex_texcoords2D())
368 && !(optionVertexNormals);
370 for (
auto f_it : _mesh.faces() ){
372 if (useMaterial && optionFaceColors) {
374 Material& material = getMaterial(_mesh, f_it, _objId);
377 if(lastMat.material_number() != material.material_number() ) {
378 _out <<
"usemtl " << material <<
'\n';
386 for(fh_it=_mesh.fh_iter(f_it); fh_it.is_valid(); ++fh_it) {
389 idx = _mesh.to_vertex_handle(*fh_it).idx() + 1;
397 if ( optionVertexTexCoords ) {
399 if ( optionVertexTexCoords && _mesh.has_halfedge_texcoords2D()) {
401 typename std::map<typename MeshT::HalfedgeHandle, int>::iterator it = vtMap.find(*fh_it);
402 if(it != vtMap.end())
403 _out << (*it).second;
404 }
else if (optionVertexTexCoords && !_mesh.has_halfedge_texcoords2D() && _mesh.has_vertex_texcoords2D()) {
406 typename std::map<typename MeshT::VertexHandle, int>::iterator it = vtMapV.find(_mesh.to_vertex_handle(*fh_it));
407 if(it != vtMapV.end())
408 _out << (*it).second;
413 if ( optionVertexNormals ) {
426 if(optionCopyTextures) {
429 bool testedOnce =
false;
431 Material& mat = (*it).second;
433 if(!mat.has_Texture())
continue;
435 QImage img(mat.map_Kd().c_str());
436 QFileInfo img_f(mat.map_Kd().c_str());
440 emit log(
LOGERR, tr(
"An error occurred when trying to copy a texture file."));
443 if(optionCreateTexFolder) {
445 QDir dir(fi.absolutePath());
446 if(!testedOnce && dir.exists(fi.absolutePath() + QDir::separator() + fi.baseName() +
"_textures")) {
447 emit log(
LOGERR, tr(
"The specified target folder already contains a subfolder called textures. Skipping!"));
450 dir.mkdir(fi.baseName() +
"_textures");
451 img.save(fi.absolutePath() + QDir::separator() + fi.baseName() +
"_textures" + QDir::separator() + img_f.fileName());
456 img.save(fi.absolutePath() + QDir::separator() + img_f.fileName());
464 texIndexFileMap_.clear();
465 textureIndexPropFetched_ =
false;
Handle for a face entity.
Add 2D texture coordinates (vertices, halfedges)
MaterialList materials_
List that contains the material properties.
VectorT< float, 3 > Vec3f
bool writeMaterial(QString _filename, MeshT &_mesh, int _objId)
writer functions
unsigned int materialErrors_
number of defect materials encountered during writing