/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Author$ *
* $Date$ *
* *
\*===========================================================================*/
#include
#include
#include
#include
#include "FileOFF.hh"
#include
#include
#include "OpenFlipper/BasePlugin/PluginFunctions.hh"
#include "OpenFlipper/common/GlobalOptions.hh"
#include
#include
/// Constructor
FileOFFPlugin::FileOFFPlugin()
: loadOptions_(0),
saveOptions_(0),
triMeshHandling_(0) {
}
//-----------------------------------------------------------------------------------------------------
void FileOFFPlugin::initializePlugin() {
}
//-----------------------------------------------------------------------------------------------------
QString FileOFFPlugin::getLoadFilters() {
return QString( tr("Object File Format files ( *.off )") );
};
//-----------------------------------------------------------------------------------------------------
QString FileOFFPlugin::getSaveFilters() {
return QString( tr("Object File Format files ( *.off )") );
};
//-----------------------------------------------------------------------------------------------------
DataType FileOFFPlugin::supportedType() {
DataType type = DATA_POLY_MESH | DATA_TRIANGLE_MESH;
return type;
}
//-----------------------------------------------------------------------------------------------------
int FileOFFPlugin::loadObject(QString _filename) {
int triMeshControl = 0; // 0 == Auto-Detect
if ( OpenFlipper::Options::gui() ){
if ( triMeshHandling_ != 0 ){
triMeshControl = triMeshHandling_->currentIndex();
} else {
triMeshControl = 0;
}
}
int objectId = -1;
if(triMeshControl == 0) {
// If Auto-Detect is selected (triMeshControl == 0)
objectId = loadPolyMeshObject(_filename);
PolyMeshObject *object = 0;
if(!PluginFunctions::getObject(objectId, object))
return -1;
for ( PolyMesh::FaceIter f_it = object->mesh()->faces_begin(); f_it != object->mesh()->faces_end() ; ++f_it) {
// Count number of vertices for the current face
uint count = 0;
for ( PolyMesh::FaceVertexIter fv_it( *(object->mesh()),f_it); fv_it; ++fv_it )
++count;
// Check if it is a triangle. If not, this is really a poly mesh
if ( count != 3 ) {
return objectId;
}
}
} else if (triMeshControl == 1) {
// If Ask is selected -> show dialog
objectId = loadPolyMeshObject(_filename);
PolyMeshObject *object = 0;
if(!PluginFunctions::getObject(objectId, object))
return -1;
for ( PolyMesh::FaceIter f_it = object->mesh()->faces_begin(); f_it != object->mesh()->faces_end() ; ++f_it) {
// Count number of vertices for the current face
uint count = 0;
for ( PolyMesh::FaceVertexIter fv_it( *(object->mesh()),f_it); fv_it; ++fv_it )
++count;
// Check if it is a triangle. If not, this is really a poly mesh
if ( count != 3 ) {
return objectId;
}
}
QMessageBox::StandardButton result = QMessageBox::question ( 0,
tr("TriMesh loaded as PolyMesh"),
tr("You opened the mesh as a poly mesh but actually its a triangle mesh. \nShould it be opened as a triangle mesh?"),
(QMessageBox::Yes | QMessageBox::No ),
QMessageBox::Yes );
// User decided to reload as triangle mesh
if ( result == QMessageBox::No ) {
return objectId;
}
} else if (triMeshControl == 2) {
// If always open as PolyMesh is selected
return loadPolyMeshObject(_filename);
} else {
// If always open as TriMesh is selected
return loadTriMeshObject(_filename);
}
// Load object as triangle mesh
if(objectId != -1) emit deleteObject(objectId);
return loadTriMeshObject(_filename);
};
//-----------------------------------------------------------------------------------------------------
/// load a triangle-mesh with given filename
int FileOFFPlugin::loadTriMeshObject(QString _filename){
int id = -1;
emit addEmptyObject(DATA_TRIANGLE_MESH, id);
TriMeshObject* object(0);
if(PluginFunctions::getObject( id, object)) {
if ( PluginFunctions::objectCount() == 1 )
object->target(true);
object->setFromFileName(_filename);
// call the local function to update names
QFileInfo f(_filename);
object->setName( f.fileName() );
std::string filename = std::string( _filename.toUtf8() );
//set options
OpenMesh::IO::Options opt = OpenMesh::IO::Options::Default;
if ( !OpenFlipper::Options::loadingSettings() &&
!OpenFlipper::Options::loadingRecentFile() && loadOptions_ != 0){
if (loadVertexColor_->isChecked())
opt += OpenMesh::IO::Options::VertexColor;
if (loadFaceColor_->isChecked())
opt += OpenMesh::IO::Options::FaceColor;
//ColorAlpha is only checked if loading binary off's
if (loadAlpha_->isChecked())
opt += OpenMesh::IO::Options::ColorAlpha;
if (loadNormals_->isChecked())
opt += OpenMesh::IO::Options::VertexNormal;
if (loadTexCoords_->isChecked())
opt += OpenMesh::IO::Options::VertexTexCoord;
}else{
//let openmesh try to read everything it can
opt += OpenMesh::IO::Options::VertexColor;
opt += OpenMesh::IO::Options::FaceColor;
opt += OpenMesh::IO::Options::VertexNormal;
opt += OpenMesh::IO::Options::VertexTexCoord;
}
// load file
bool ok = OpenMesh::IO::read_mesh( (*object->mesh()) , filename, opt );
if (!ok)
{
std::cerr << "Plugin FileOFF : Read error for Triangle Mesh\n";
emit deleteObject( object->id() );
return -1;
}
object->mesh()->update_normals();
object->update();
object->show();
emit log(LOGINFO,object->getObjectinfo());
emit openedFile( object->id() );
return object->id();
} else {
emit log(LOGERR,"Error : Could not create new triangle mesh object.");
return -1;
}
}
//-----------------------------------------------------------------------------------------------------
/// load a poly-mesh with given filename
int FileOFFPlugin::loadPolyMeshObject(QString _filename){
int id = -1;
emit addEmptyObject(DATA_POLY_MESH, id);
PolyMeshObject* object(0);
if(PluginFunctions::getObject( id, object)) {
if (PluginFunctions::objectCount() == 1 )
object->target(true);
object->setFromFileName(_filename);
// call the local function to update names
QFileInfo f(_filename);
object->setName( f.fileName() );
std::string filename = std::string( _filename.toUtf8() );
//set options
OpenMesh::IO::Options opt = OpenMesh::IO::Options::Default;
if ( !OpenFlipper::Options::loadingSettings() &&
!OpenFlipper::Options::loadingRecentFile() && loadOptions_ != 0){
if (loadVertexColor_->isChecked())
opt += OpenMesh::IO::Options::VertexColor;
if (loadFaceColor_->isChecked())
opt += OpenMesh::IO::Options::FaceColor;
// ColorAlpha is only checked if loading binary off's
if (loadAlpha_->isChecked())
opt += OpenMesh::IO::Options::ColorAlpha;
if (loadNormals_->isChecked())
opt += OpenMesh::IO::Options::VertexNormal;
if (loadTexCoords_->isChecked())
opt += OpenMesh::IO::Options::VertexTexCoord;
} else {
// Let openmesh try to read everything it can
opt += OpenMesh::IO::Options::VertexColor;
opt += OpenMesh::IO::Options::FaceColor;
opt += OpenMesh::IO::Options::VertexNormal;
opt += OpenMesh::IO::Options::VertexTexCoord;
}
// load file
bool ok = OpenMesh::IO::read_mesh( (*object->mesh()) , filename, opt );
if (!ok)
{
std::cerr << "Plugin FileOFF : Read error for Poly Mesh\n";
emit deleteObject( object->id() );
return -1;
}
object->mesh()->update_normals();
object->update();
object->show();
emit log(LOGINFO,object->getObjectinfo());
emit openedFile( object->id() );
return object->id();
} else {
emit log(LOGERR,"Error : Could not create new poly mesh object.");
return -1;
}
}
//-----------------------------------------------------------------------------------------------------
bool FileOFFPlugin::saveObject(int _id, QString _filename)
{
BaseObjectData* object;
PluginFunctions::getObject(_id,object);
std::string filename = std::string( _filename.toUtf8() );
if ( object->dataType( DATA_POLY_MESH ) ) {
object->setName(_filename.section(OpenFlipper::Options::dirSeparator(),-1));
object->path(_filename.section(OpenFlipper::Options::dirSeparator(),0,-2) );
PolyMeshObject* polyObj = dynamic_cast( object );
if (OpenMesh::IO::write_mesh(*polyObj->mesh(), filename.c_str()) ){
emit log(LOGINFO, tr("Saved object to ") + object->path() + OpenFlipper::Options::dirSeparator() + object->name() );
return true;
}else{
emit log(LOGERR, tr("Unable to save ") + object->path() + OpenFlipper::Options::dirSeparator() + object->name());
return false;
}
} else if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
object->setName(_filename.section(OpenFlipper::Options::dirSeparator(),-1));
object->path(_filename.section(OpenFlipper::Options::dirSeparator(),0,-2) );
TriMeshObject* triObj = dynamic_cast( object );
OpenMesh::IO::Options opt = OpenMesh::IO::Options::Default;
if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0){
if (saveBinary_->isChecked())
opt += OpenMesh::IO::Options::Binary;
if (saveVertexColor_->isChecked()){
opt += OpenMesh::IO::Options::VertexColor;
}
if (saveFaceColor_->isChecked()){
opt += OpenMesh::IO::Options::FaceColor;
}
if (saveAlpha_->isChecked()){
opt += OpenMesh::IO::Options::ColorAlpha;
}
if (saveNormals_->isChecked())
opt += OpenMesh::IO::Options::VertexNormal;
if (saveTexCoords_->isChecked())
opt += OpenMesh::IO::Options::VertexTexCoord;
}
if (OpenMesh::IO::write_mesh(*triObj->mesh(), filename.c_str(),opt) ) {
emit log(LOGINFO, tr("Saved object to ") + object->path() + OpenFlipper::Options::dirSeparator() + object->name() );
return true;
} else {
emit log(LOGERR, tr("Unable to save ") + object->path() + OpenFlipper::Options::dirSeparator() + object->name());
return false;
}
} else {
emit log(LOGERR, tr("Unable to save (object is not a compatible mesh type)"));
return false;
}
}
//-----------------------------------------------------------------------------------------------------
QWidget* FileOFFPlugin::saveOptionsWidget(QString _currentFilter) {
if (saveOptions_ == 0){
//generate widget
saveOptions_ = new QWidget();
QVBoxLayout* layout = new QVBoxLayout();
layout->setAlignment(Qt::AlignTop);
saveBinary_ = new QCheckBox("Save Binary");
layout->addWidget(saveBinary_);
saveVertexColor_ = new QCheckBox("Save Vertex Colors");
layout->addWidget(saveVertexColor_);
saveFaceColor_ = new QCheckBox("Save Face Colors");
layout->addWidget(saveFaceColor_);
saveAlpha_ = new QCheckBox("Save Color Alpha");
layout->addWidget(saveAlpha_);
saveNormals_ = new QCheckBox("Save Normals");
layout->addWidget(saveNormals_);
saveTexCoords_ = new QCheckBox("Save TexCoords");
layout->addWidget(saveTexCoords_);
saveDefaultButton_ = new QPushButton("Make Default");
layout->addWidget(saveDefaultButton_);
saveOptions_->setLayout(layout);
connect(saveDefaultButton_, SIGNAL(clicked()), this, SLOT(slotSaveDefault()));
saveBinary_->setChecked( OpenFlipperSettings().value("FileOff/Save/Binary",true).toBool() );
saveVertexColor_->setChecked( OpenFlipperSettings().value("FileOff/Save/VertexColor",true).toBool() );
saveFaceColor_->setChecked( OpenFlipperSettings().value("FileOff/Save/FaceColor",true).toBool() );
saveAlpha_->setChecked( OpenFlipperSettings().value("FileOff/Save/Alpha",true).toBool() );
saveNormals_->setChecked( OpenFlipperSettings().value("FileOff/Save/Normals",true).toBool() );
saveTexCoords_->setChecked( OpenFlipperSettings().value("FileOff/Save/TexCoords",true).toBool() );
}
return saveOptions_;
}
//-----------------------------------------------------------------------------------------------------
QWidget* FileOFFPlugin::loadOptionsWidget(QString /*_currentFilter*/) {
if (loadOptions_ == 0){
//generate widget
loadOptions_ = new QWidget();
QVBoxLayout* layout = new QVBoxLayout();
layout->setAlignment(Qt::AlignTop);
QLabel* label = new QLabel(tr("If PolyMesh is a Triangle Mesh:"));
layout->addWidget(label);
triMeshHandling_ = new QComboBox();
triMeshHandling_->addItem( tr("Auto-Detect") );
triMeshHandling_->addItem( tr("Ask") );
triMeshHandling_->addItem( tr("Always open as PolyMesh") );
triMeshHandling_->addItem( tr("Always open as TriangleMesh") );
layout->addWidget(triMeshHandling_);
loadVertexColor_ = new QCheckBox("Load Vertex Colors");
layout->addWidget(loadVertexColor_);
loadFaceColor_ = new QCheckBox("Load Face Colors");
layout->addWidget(loadFaceColor_);
loadAlpha_ = new QCheckBox("Load Color Alpha");
layout->addWidget(loadAlpha_);
loadNormals_ = new QCheckBox("Load Normals");
layout->addWidget(loadNormals_);
loadTexCoords_ = new QCheckBox("Load TexCoords");
layout->addWidget(loadTexCoords_);
loadDefaultButton_ = new QPushButton("Make Default");
layout->addWidget(loadDefaultButton_);
loadOptions_->setLayout(layout);
connect(loadDefaultButton_, SIGNAL(clicked()), this, SLOT(slotLoadDefault()));
triMeshHandling_->setCurrentIndex(OpenFlipperSettings().value("FileOff/Load/TriMeshHandling",2).toInt() );
loadVertexColor_->setChecked( OpenFlipperSettings().value("FileOff/Load/VertexColor",true).toBool() );
loadFaceColor_->setChecked( OpenFlipperSettings().value("FileOff/Load/FaceColor",true).toBool() );
loadAlpha_->setChecked( OpenFlipperSettings().value("FileOff/Load/Alpha",true).toBool() );
loadNormals_->setChecked( OpenFlipperSettings().value("FileOff/Load/Normals",true).toBool() );
loadTexCoords_->setChecked( OpenFlipperSettings().value("FileOff/Load/TexCoords",true).toBool() );
}
return loadOptions_;
}
void FileOFFPlugin::slotLoadDefault() {
OpenFlipperSettings().setValue( "FileOff/Load/VertexColor", loadVertexColor_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Load/FaceColor", loadFaceColor_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Load/Alpha", loadAlpha_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Load/Normals", loadNormals_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Load/TexCoords", loadTexCoords_->isChecked() );
OpenFlipperSettings().setValue("FileOff/Load/TriMeshHandling", triMeshHandling_->currentIndex() );
}
void FileOFFPlugin::slotSaveDefault() {
OpenFlipperSettings().setValue( "FileOff/Save/Binary", saveBinary_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Save/VertexColor", saveVertexColor_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Save/FaceColor", saveFaceColor_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Save/Alpha", saveAlpha_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Save/Normals", saveNormals_->isChecked() );
OpenFlipperSettings().setValue( "FileOff/Save/TexCoords", saveTexCoords_->isChecked() );
}
Q_EXPORT_PLUGIN2( fileoffplugin , FileOFFPlugin );