51 #define FILEOBJPLUGIN_C
55 #include <OpenMesh/Core/Utils/color_cast.hh>
56 #include <OpenMesh/Core/Geometry/VectorT.hh>
61 template<
class MeshT >
64 bool optionColorAlpha =
false;
65 bool optionTextures =
false;
66 bool optionCopyTextures =
false;
67 bool optionCreateTexFolder =
false;
70 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0) {
71 optionColorAlpha = saveAlpha_->isChecked();
72 optionTextures = saveTextures_->isChecked();
73 optionCopyTextures = saveCopyTextures_->isChecked();
74 optionCreateTexFolder = saveCreateTexFolder_->isChecked();
78 std::fstream matStream( _filename.toStdString().c_str(), std::ios_base::out );
82 emit log(
LOGERR, tr(
"writeMaterial : cannot not open file %1").arg(_filename) );
93 typename MeshT::FaceIter f_it;
94 typename MeshT::FaceIter f_end = _mesh.faces_end();
97 for (f_it = _mesh.faces_begin(); f_it != f_end; ++f_it){
98 getMaterial(_mesh, *f_it, _objId);
103 Material& mat = (*it).second;
104 matStream <<
"newmtl " << mat <<
'\n';
105 matStream <<
"Ka 0.5000 0.5000 0.5000" <<
'\n';
107 matStream <<
"Kd " << c[0] <<
" " << c[1] <<
" " << c[2] <<
'\n';
108 if(optionColorAlpha) {
109 matStream <<
"Tr " << mat.Tr() <<
'\n';
111 matStream <<
"illum 1" <<
'\n';
114 if(optionTextures && mat.has_Texture()) {
115 if(optionCopyTextures) {
117 QFileInfo file(mat.map_Kd().c_str());
118 if(optionCreateTexFolder) {
119 QFileInfo materialFilename(_filename);
121 matStream <<
"map_Kd " << materialFilename.baseName().toStdString() <<
"_textures" << QDir::separator().toLatin1()
122 << file.fileName().toStdString() <<
'\n';
124 matStream <<
"map_Kd " << file.fileName().toStdString() <<
'\n';
128 matStream <<
"map_Kd " << mat.map_Kd() <<
'\n';
142 template<
class MeshT >
146 bool optionColorAlpha =
false;
147 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0)
148 optionColorAlpha = saveAlpha_->isChecked();
154 if(!textureIndexPropFetched_) {
155 emit textureIndexPropertyName(_objId, textureIndexPropertyName_);
156 textureIndexPropFetched_ =
true;
161 if ( _mesh.get_property_handle(texture_index_property, textureIndexPropertyName_.toStdString()) ) {
162 texIndex = _mesh.property(texture_index_property, _fh);
163 }
else if ( _mesh.get_property_handle(texture_index_property,
"f:textureindex") ) {
164 texIndex = _mesh.property(texture_index_property, _fh);
165 }
else if(_mesh.has_face_texture_index()) {
166 texIndex = _mesh.texture_index(_fh);
169 emit getCurrentTexture(_objId, texName);
170 if(texName !=
"NONE")
171 emit textureIndex(texName, _objId, texIndex);
175 bool hasTexture =
false;
180 std::map<int,QString>::iterator it = texIndexFileMap_.find(texIndex);
182 if(it != texIndexFileMap_.end()) {
184 filename = (*it).second;
189 emit textureName(_objId, texIndex, texName);
191 if(texName !=
"NOT_FOUND") {
192 emit textureFilename( _objId, texName, filename );
194 texIndexFileMap_.insert(std::pair<int,QString>(texIndex, filename));
205 if(((*it).second).Kd() ==
ACG::Vec3f(c[0], c[1], c[2]) &&
206 ((optionColorAlpha && ((*it).second).Tr() == c[3]) || !optionColorAlpha))
210 QString mKd(((*it).second).map_Kd().c_str());
211 if((((*it).second).Kd() ==
ACG::Vec3f(c[0], c[1], c[2]) &&
212 ((optionColorAlpha && ((*it).second).Tr() == c[3]) || !optionColorAlpha)) &&
213 (filename == mKd && ((*it).second).map_Kd_index() == texIndex))
221 mat.set_Kd(c[0], c[1], c[2]);
223 if(optionColorAlpha) mat.set_Tr(c[3]);
227 mat.set_map_Kd(filename.toStdString(), texIndex);
229 materials_.insert(std::make_pair(QString(
"Material%1").arg(mat.material_number()).toStdString(), mat));
240 template<
class MeshT >
241 bool FileOBJPlugin::writeMesh(std::ostream& _out, QString _filename, MeshT& _mesh,
int _objId){
243 unsigned int i, nV, idx;
246 typename MeshT::VertexHandle vh;
247 bool useMaterial =
false;
250 bool optionFaceColors =
false;
251 bool optionVertexNormals =
false;
252 bool optionVertexTexCoords =
true;
253 bool optionTextures =
false;
254 bool optionCopyTextures =
false;
255 bool optionCreateTexFolder =
false;
257 QFileInfo fi(_filename);
260 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0) {
261 optionFaceColors = saveFaceColor_->isChecked();
262 optionVertexNormals = saveNormals_->isChecked();
263 optionVertexTexCoords = saveTexCoords_->isChecked();
264 optionTextures = saveTextures_->isChecked();
265 optionCopyTextures = saveCopyTextures_->isChecked();
266 optionCreateTexFolder = saveCreateTexFolder_->isChecked();
267 _out.precision(savePrecision_->value());
272 if ( optionFaceColors || optionTextures ){
274 QString matFile = fi.absolutePath() + QDir::separator() + fi.baseName() +
".mtl";
280 _out <<
"# " << _mesh.n_vertices() <<
" vertices, ";
281 _out << _mesh.n_faces() <<
" faces" <<
'\n';
284 if (useMaterial && optionFaceColors )
285 _out <<
"mtllib " << fi.baseName().toStdString() <<
".mtl" <<
'\n';
290 std::map<typename MeshT::VertexHandle, int> vtMapV;
294 for (i=0, nV=_mesh.n_vertices(); i<nV; ++i)
296 vh =
typename MeshT::VertexHandle(i);
298 n = _mesh.normal(vh);
300 if ( _mesh.has_vertex_texcoords2D() && !_mesh.has_halfedge_texcoords2D() )
301 t = _mesh.texcoord2D(vh);
304 _out <<
"v " << v[0] <<
" "<< v[1] <<
" "<< v[2] <<
'\n';
307 if ( optionVertexNormals)
308 _out <<
"vn " << n[0] <<
" "<< n[1] <<
" "<< n[2] <<
'\n';
311 if ( optionVertexTexCoords && _mesh.has_vertex_texcoords2D() && !_mesh.has_halfedge_texcoords2D()) {
312 _out <<
"vt " << t[0] <<
" "<< t[1] <<
'\n';
313 vtMapV.insert(std::pair<typename MeshT::VertexHandle, int>(vh, cf));
318 typename MeshT::FaceVertexIter fv_it;
319 typename MeshT::FaceHalfedgeIter fh_it;
320 typename MeshT::FaceIter f_it;
325 std::map<typename MeshT::HalfedgeHandle, int> vtMap;
328 if(optionVertexTexCoords && _mesh.has_halfedge_texcoords2D()) {
330 for (f_it = _mesh.faces_begin(); f_it != _mesh.faces_end(); ++f_it) {
331 for(fh_it=_mesh.fh_iter(*f_it); fh_it.is_valid(); ++fh_it) {
333 _out <<
"vt " << t[0] <<
" " << t[1] <<
'\n';
334 vtMap.insert(std::pair<typename MeshT::HalfedgeHandle, int>(*fh_it, count));
343 bool vertexOnly = !(optionVertexTexCoords && _mesh.has_halfedge_texcoords2D())
344 && !(optionVertexTexCoords && !_mesh.has_halfedge_texcoords2D() && _mesh.has_vertex_texcoords2D())
345 && !(optionVertexNormals);
347 for (f_it = _mesh.faces_begin(); f_it != _mesh.faces_end(); ++f_it){
349 if (useMaterial && optionFaceColors) {
351 Material& material = getMaterial(_mesh, *f_it, _objId);
354 if(lastMat != material) {
355 _out <<
"usemtl " << material <<
'\n';
363 for(fh_it=_mesh.fh_iter(*f_it); fh_it.is_valid(); ++fh_it) {
366 idx = _mesh.to_vertex_handle(*fh_it).idx() + 1;
374 if ( optionVertexTexCoords ) {
376 if ( optionVertexTexCoords && _mesh.has_halfedge_texcoords2D()) {
378 typename std::map<typename MeshT::HalfedgeHandle, int>::iterator it = vtMap.find(*fh_it);
379 if(it != vtMap.end())
380 _out << (*it).second;
381 }
else if (optionVertexTexCoords && !_mesh.has_halfedge_texcoords2D() && _mesh.has_vertex_texcoords2D()) {
383 typename std::map<typename MeshT::VertexHandle, int>::iterator it = vtMapV.find(_mesh.to_vertex_handle(*fh_it));
384 if(it != vtMapV.end())
385 _out << (*it).second;
390 if ( optionVertexNormals ) {
403 if(optionCopyTextures) {
406 bool testedOnce =
false;
408 Material& mat = (*it).second;
410 if(!mat.has_Texture())
continue;
412 QImage img(mat.map_Kd().c_str());
413 QFileInfo img_f(mat.map_Kd().c_str());
417 emit log(
LOGERR, tr(
"An error occurred when trying to copy a texture file."));
420 if(optionCreateTexFolder) {
422 QDir dir(fi.absolutePath());
423 if(!testedOnce && dir.exists(fi.absolutePath() + QDir::separator() + fi.baseName() +
"_textures")) {
424 emit log(
LOGERR, tr(
"The specified target folder already contains a subfolder called textures. Skipping!"));
427 dir.mkdir(fi.baseName() +
"_textures");
428 img.save(fi.absolutePath() + QDir::separator() + fi.baseName() +
"_textures" + QDir::separator() + img_f.fileName());
433 img.save(fi.absolutePath() + QDir::separator() + img_f.fileName());
440 texIndexFileMap_.clear();
441 textureIndexPropFetched_ =
false;
bool writeMaterial(QString _filename, MeshT &_mesh, int _objId)
writer functions
VectorT< float, 3 > Vec3f
Add 2D texture coordinates (vertices, halfedges)
Handle for a face entity.
MaterialList materials_
List that contains the material properties.