45#define FILEOBJPLUGIN_C
49#include <OpenMesh/Core/Utils/color_cast.hh>
50#include <OpenMesh/Core/Geometry/VectorT.hh>
55template<
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 for (
auto f_it : _mesh.faces()){
91 getMaterial(_mesh, f_it, _objId);
96 Material& mat = (*it).second;
97 matStream <<
"newmtl " << mat <<
'\n';
98 matStream <<
"Ka 0.5000 0.5000 0.5000" <<
'\n';
100 matStream <<
"Kd " << c[0] <<
" " << c[1] <<
" " << c[2] <<
'\n';
101 if(optionColorAlpha) {
102 matStream <<
"Tr " << mat.Tr() <<
'\n';
104 matStream <<
"illum 1" <<
'\n';
107 if(optionTextures && mat.has_Texture()) {
108 if(optionCopyTextures) {
110 QFileInfo file(mat.map_Kd().c_str());
111 if(optionCreateTexFolder) {
112 QFileInfo materialFilename(_filename);
114 matStream <<
"map_Kd " << materialFilename.baseName().toStdString() <<
"_textures" << QDir::separator().toLatin1()
115 << file.fileName().toStdString() <<
'\n';
117 matStream <<
"map_Kd " << file.fileName().toStdString() <<
'\n';
121 matStream <<
"map_Kd " << mat.map_Kd() <<
'\n';
135template<
class MeshT >
138 bool optionFaceColors =
false;
139 bool optionFaceColorsOverride =
false;
140 bool optionColorAlpha =
false;
142 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0) {
143 optionFaceColors = saveFaceColor_->isChecked();
144 optionFaceColorsOverride = saveFaceColorOverride_->isChecked();
145 optionColorAlpha = saveAlpha_->isChecked();
151 if ( optionFaceColors && !optionFaceColorsOverride ) {
155 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]) ) {
173 if(!textureIndexPropFetched_) {
174 emit textureIndexPropertyName(_objId, textureIndexPropertyName_);
175 textureIndexPropFetched_ =
true;
180 if ( _mesh.get_property_handle(texture_index_property, textureIndexPropertyName_.toStdString()) ) {
181 texIndex = _mesh.property(texture_index_property, _fh);
182 }
else if ( _mesh.get_property_handle(texture_index_property,
"f:textureindex") ) {
183 texIndex = _mesh.property(texture_index_property, _fh);
184 }
else if(_mesh.has_face_texture_index()) {
185 texIndex = _mesh.texture_index(_fh);
188 emit getCurrentTexture(_objId, texName);
189 if(texName !=
"NONE")
190 emit textureIndex(texName, _objId, texIndex);
194 bool hasTexture =
false;
199 std::map<int,QString>::iterator it = texIndexFileMap_.find(texIndex);
201 if(it != texIndexFileMap_.end()) {
203 filename = (*it).second;
208 emit textureName(_objId, texIndex, texName);
210 if(texName !=
"NOT_FOUND") {
211 emit textureFilename( _objId, texName, filename );
213 texIndexFileMap_.insert(std::pair<int,QString>(texIndex, filename));
224 if(((*it).second).Kd() ==
ACG::Vec3f(c[0], c[1], c[2]) &&
225 ((optionColorAlpha && ((*it).second).Tr() == c[3]) || !optionColorAlpha))
229 QString mKd(((*it).second).map_Kd().c_str());
230 if((((*it).second).Kd() ==
ACG::Vec3f(c[0], c[1], c[2]) &&
231 ((optionColorAlpha && ((*it).second).Tr() == c[3]) || !optionColorAlpha)) &&
232 (filename == mKd && ((*it).second).map_Kd_index() == texIndex))
240 mat.set_Kd(c[0], c[1], c[2]);
242 if(optionColorAlpha) mat.set_Tr(c[3]);
246 mat.set_map_Kd(filename.toStdString(), texIndex);
248 materials_.insert(std::make_pair(QString(
"Material%1").arg(mat.material_number()).toStdString(), mat));
259template<
class MeshT >
260bool FileOBJPlugin::writeMesh(std::ostream& _out, QString _filename,
MeshT& _mesh,
int _objId){
262 unsigned int i, nV, idx;
265 typename MeshT::VertexHandle vh;
266 bool useMaterial =
false;
269 bool optionFaceColors =
false;
270 bool optionVertexNormals =
false;
271 bool optionVertexTexCoords =
true;
272 bool optionTextures =
false;
273 bool optionCopyTextures =
false;
274 bool optionCreateTexFolder =
false;
276 QFileInfo fi(_filename);
279 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0) {
280 optionFaceColors = saveFaceColor_->isChecked();
281 optionVertexNormals = saveNormals_->isChecked();
282 optionVertexTexCoords = saveTexCoords_->isChecked();
283 optionTextures = saveTextures_->isChecked();
284 optionCopyTextures = saveCopyTextures_->isChecked();
285 optionCreateTexFolder = saveCreateTexFolder_->isChecked();
286 _out.precision(savePrecision_->value());
291 if ( optionFaceColors || optionTextures ){
293 QString matFile = fi.absolutePath() + QDir::separator() + fi.baseName() +
".mtl";
299 _out <<
"# " << _mesh.
n_vertices() <<
" vertices, ";
300 _out << _mesh.
n_faces() <<
" faces" <<
'\n';
303 if (useMaterial && optionFaceColors )
304 _out <<
"mtllib " << fi.baseName().toStdString() <<
".mtl" <<
'\n';
309 std::map<typename MeshT::VertexHandle, int> vtMapV;
315 vh =
typename MeshT::VertexHandle(i);
319 if ( _mesh.has_vertex_texcoords2D() && !_mesh.has_halfedge_texcoords2D() )
320 t = _mesh.texcoord2D(vh);
323 _out <<
"v " << v[0] <<
" "<< v[1] <<
" "<< v[2] <<
'\n';
326 if ( optionVertexNormals)
327 _out <<
"vn " << n[0] <<
" "<< n[1] <<
" "<< n[2] <<
'\n';
330 if ( optionVertexTexCoords && _mesh.has_vertex_texcoords2D() && !_mesh.has_halfedge_texcoords2D()) {
331 _out <<
"vt " << t[0] <<
" "<< t[1] <<
'\n';
332 vtMapV.insert(std::pair<typename MeshT::VertexHandle, int>(vh, cf));
340 std::map<typename MeshT::HalfedgeHandle, int> vtMap;
343 if(optionVertexTexCoords && _mesh.has_halfedge_texcoords2D()) {
345 for (
auto f_it : _mesh.faces() ) {
346 for(
auto fh_it : f_it.halfedges()) {
347 typename MeshT::TexCoord2D t = _mesh.texcoord2D(fh_it);
348 _out <<
"vt " << t[0] <<
" " << t[1] <<
'\n';
349 vtMap.insert(std::pair<typename MeshT::HalfedgeHandle, int>(fh_it, count));
358 bool vertexOnly = !(optionVertexTexCoords && _mesh.has_halfedge_texcoords2D())
359 && !(optionVertexTexCoords && !_mesh.has_halfedge_texcoords2D() && _mesh.has_vertex_texcoords2D())
360 && !(optionVertexNormals);
362 for (
auto f_it : _mesh.faces() ){
364 if (useMaterial && optionFaceColors) {
366 Material& material = getMaterial(_mesh, f_it, _objId);
369 if(lastMat.material_number() != material.material_number() ) {
370 _out <<
"usemtl " << material <<
'\n';
378 for(
auto fh_it : f_it.halfedges()) {
381 idx = fh_it.to().idx() + 1;
389 if ( optionVertexTexCoords ) {
391 if ( optionVertexTexCoords && _mesh.has_halfedge_texcoords2D()) {
393 typename std::map<typename MeshT::HalfedgeHandle, int>::iterator it = vtMap.find(fh_it);
394 if(it != vtMap.end())
395 _out << (*it).second;
396 }
else if (optionVertexTexCoords && !_mesh.has_halfedge_texcoords2D() && _mesh.has_vertex_texcoords2D()) {
398 typename std::map<typename MeshT::VertexHandle, int>::iterator it = vtMapV.find(_mesh.
to_vertex_handle(fh_it));
399 if(it != vtMapV.end())
400 _out << (*it).second;
405 if ( optionVertexNormals ) {
418 if(optionCopyTextures) {
421 bool testedOnce =
false;
423 Material& mat = (*it).second;
425 if(!mat.has_Texture())
continue;
427 QImage img(mat.map_Kd().c_str());
428 QFileInfo img_f(mat.map_Kd().c_str());
432 emit log(
LOGERR, tr(
"An error occurred when trying to copy a texture file."));
435 if(optionCreateTexFolder) {
437 QDir dir(fi.absolutePath());
438 if(!testedOnce && dir.exists(fi.absolutePath() + QDir::separator() + fi.baseName() +
"_textures")) {
439 emit log(
LOGERR, tr(
"The specified target folder already contains a subfolder called textures. Skipping!"));
442 dir.mkdir(fi.baseName() +
"_textures");
443 img.save(fi.absolutePath() + QDir::separator() + fi.baseName() +
"_textures" + QDir::separator() + img_f.fileName());
448 img.save(fi.absolutePath() + QDir::separator() + img_f.fileName());
456 texIndexFileMap_.clear();
457 textureIndexPropFetched_ =
false;
unsigned int materialErrors_
number of defect materials encountered during writing
bool writeMaterial(QString _filename, MeshT &_mesh, int _objId)
writer functions
MaterialList materials_
List that contains the material properties.
PointT normal(HalfFaceHandle _hfh) const
size_t n_vertices() const override
Get number of vertices in mesh.
size_t n_faces() const override
Get number of faces in mesh.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
VectorT< float, 3 > Vec3f
Handle for a face entity.