mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-17 01:54:42 +00:00
fix behaviour for flat shading, possibility to not save textures and set default texture quality to -1
This commit is contained in:
parent
bea50eca85
commit
203632f2fb
@ -168,7 +168,7 @@ public:
|
||||
void setVisible(bool vis = true) { visible = vis;}
|
||||
|
||||
std::list<std::string> loadTextures(GLLogStream* log = nullptr, vcg::CallBackPos* cb = nullptr);
|
||||
void saveTextures(const QString& basePath, int quality = 66, GLLogStream* log = nullptr, vcg::CallBackPos* cb = nullptr);
|
||||
void saveTextures(const QString& basePath, int quality = -1, GLLogStream* log = nullptr, vcg::CallBackPos* cb = nullptr);
|
||||
|
||||
QImage getTexture(const std::string& tn) const;
|
||||
void clearTextures();
|
||||
|
||||
@ -282,7 +282,7 @@ public:
|
||||
const QString& format,
|
||||
const QString& /*fileName*/,
|
||||
const QImage& /*image*/,
|
||||
int /*quality*/ = 66,
|
||||
int /*quality*/ = -1,
|
||||
vcg::CallBackPos* /*cb*/ = nullptr)
|
||||
{
|
||||
wrongSaveFormat(format);
|
||||
|
||||
@ -249,7 +249,7 @@ void saveMeshWithStandardParameters(
|
||||
|
||||
ioPlugin->save(extension, fileName, m, capability, saveParams, cb);
|
||||
m.setFileName(fileName);
|
||||
m.saveTextures(fi.absolutePath(), 66, log, cb);
|
||||
m.saveTextures(fi.absolutePath(), -1, log, cb);
|
||||
}
|
||||
|
||||
void saveAllMeshes(
|
||||
|
||||
@ -75,7 +75,7 @@ QImage loadImage(
|
||||
void saveImage(
|
||||
const QString& filename,
|
||||
const QImage& image,
|
||||
int quality = 66,
|
||||
int quality = -1,
|
||||
GLLogStream* log = nullptr,
|
||||
vcg::CallBackPos* cb = nullptr);
|
||||
|
||||
|
||||
@ -107,6 +107,11 @@ std::vector<std::string> SaveMeshAttributesDialog::getTextureNames() const
|
||||
return textureNames;
|
||||
}
|
||||
|
||||
bool SaveMeshAttributesDialog::saveTextures() const
|
||||
{
|
||||
return ui->saveTextureCheckBox->isChecked();
|
||||
}
|
||||
|
||||
int SaveMeshAttributesDialog::getTextureQuality() const
|
||||
{
|
||||
return textureQuality;
|
||||
@ -304,3 +309,19 @@ void SaveMeshAttributesDialog::updateMask()
|
||||
|
||||
this->mask=newmask;
|
||||
}
|
||||
|
||||
void SaveMeshAttributesDialog::on_saveTextureCheckBox_stateChanged(int arg1)
|
||||
{
|
||||
ui->textureQualitySpinBox->setEnabled(arg1 == Qt::Checked);
|
||||
ui->textureQualityLabel->setEnabled(arg1 == Qt::Checked);
|
||||
}
|
||||
|
||||
void SaveMeshAttributesDialog::on_textureQualitySpinBox_valueChanged(int arg1)
|
||||
{
|
||||
if (arg1 == -1){
|
||||
ui->textureQualitySpinBox->setSuffix(" (default)");
|
||||
}
|
||||
else {
|
||||
ui->textureQualitySpinBox->setSuffix("");
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +64,7 @@ public:
|
||||
int getNewMask() const;
|
||||
RichParameterList getNewAdditionalSaveParameters() const;
|
||||
std::vector<std::string> getTextureNames() const;
|
||||
bool saveTextures() const;
|
||||
int getTextureQuality() const;
|
||||
|
||||
private slots:
|
||||
@ -75,6 +76,10 @@ private slots:
|
||||
void on_AllButton_clicked();
|
||||
void on_NoneButton_clicked();
|
||||
|
||||
void on_saveTextureCheckBox_stateChanged(int arg1);
|
||||
|
||||
void on_textureQualitySpinBox_valueChanged(int arg1);
|
||||
|
||||
private:
|
||||
void setMaskCapability();
|
||||
void checkAndEnable(QCheckBox *qcb,int bit, int capabilityBits, int defaultBits);
|
||||
|
||||
@ -237,6 +237,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="saveTextureCheckBox">
|
||||
<property name="text">
|
||||
<string>Save Texture File(s)</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
@ -270,6 +283,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="textureQualitySpinBox">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
@ -277,7 +293,7 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>66</number>
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@ -799,7 +799,7 @@ void LayerDialog::addDefaultNotes(QTreeWidgetItem * parent, MeshModel *meshModel
|
||||
|
||||
for(const std::string& name: vertPointNames) {
|
||||
QTreeWidgetItem *vertItem = new QTreeWidgetItem();
|
||||
vertItem->setText(2, QString("Vert (point):"));
|
||||
vertItem->setText(2, QString("Vert (vec3):"));
|
||||
vertItem->setText(3, QString(name.c_str()));
|
||||
parent->addChild(vertItem);
|
||||
updateColumnNumber(vertItem);
|
||||
@ -815,7 +815,7 @@ void LayerDialog::addDefaultNotes(QTreeWidgetItem * parent, MeshModel *meshModel
|
||||
|
||||
for(const std::string& name: facePointNames) {
|
||||
QTreeWidgetItem *vertItem = new QTreeWidgetItem();
|
||||
vertItem->setText(2, QString("Face (point):"));
|
||||
vertItem->setText(2, QString("Face (vec3):"));
|
||||
vertItem->setText(3, QString(name.c_str()));
|
||||
parent->addChild(vertItem);
|
||||
updateColumnNumber(vertItem);
|
||||
|
||||
@ -152,12 +152,9 @@ private slots:
|
||||
public:
|
||||
|
||||
bool exportMesh(QString fileName,MeshModel* mod,const bool saveAllPossibleAttributes);
|
||||
bool loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, const std::list<MeshModel*>& meshList, std::list<int>& maskList, const RichParameterList& prePar, const Matrix44m &mtr=Matrix44m::Identity(), bool isareload = false, MLRenderingData* rendOpt = NULL);
|
||||
|
||||
void computeRenderingDataOnLoading(MeshModel* mm,bool isareload, MLRenderingData* rendOpt = NULL);
|
||||
|
||||
bool loadMeshWithStandardParams(QString& fullPath, MeshModel* mm, const Matrix44m &mtr = Matrix44m::Identity(), bool isareload = false, MLRenderingData* rendOpt = NULL);
|
||||
|
||||
void defaultPerViewRenderingData(MLRenderingData& dt) const;
|
||||
void getRenderingData(int mid,MLRenderingData& dt) const;
|
||||
void setRenderingData(int mid,const MLRenderingData& dt);
|
||||
|
||||
@ -2006,137 +2006,6 @@ bool MainWindow::importRaster(const QString& fileImg)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::loadMesh(const QString& fileName, IOPlugin *pCurrentIOPlugin, const std::list<MeshModel*>& meshList, std::list<int>& maskList, const RichParameterList& prePar, const Matrix44m &mtr, bool isareload, MLRenderingData* rendOpt)
|
||||
{
|
||||
if ((GLA() == NULL))
|
||||
return false;
|
||||
|
||||
QFileInfo fi(fileName);
|
||||
QString extension = fi.suffix();
|
||||
|
||||
// the original directory path before we switch it
|
||||
QString origDir = QDir::current().path();
|
||||
|
||||
// this change of dir is needed for subsequent textures/materials loading
|
||||
QDir::setCurrent(fi.absoluteDir().absolutePath());
|
||||
|
||||
// Adjust the file name after changing the directory
|
||||
QString fileNameSansDir = fi.fileName();
|
||||
|
||||
// retrieving corresponding IO plugin
|
||||
if (pCurrentIOPlugin == 0)
|
||||
{
|
||||
QString errorMsgFormat = "Error encountered while opening file:\n\"%1\"\n\nError details: The \"%2\" file extension does not correspond to any supported format.";
|
||||
QMessageBox::critical(this, tr("Opening Error"), errorMsgFormat.arg(fileName, extension));
|
||||
QDir::setCurrent(origDir); // undo the change of directory before leaving
|
||||
return false;
|
||||
}
|
||||
meshDoc()->setBusy(true);
|
||||
pCurrentIOPlugin->setLog(&meshDoc()->Log);
|
||||
|
||||
unsigned int nMeshes = pCurrentIOPlugin->numberMeshesContainedInFile(extension, fileNameSansDir, prePar);
|
||||
if (nMeshes != meshList.size()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Opening Failure"),
|
||||
"Expected one mesh but " + fileName + " contains " + nMeshes + " meshes.");
|
||||
meshDoc()->setBusy(false);
|
||||
QDir::setCurrent(origDir); // undo the change of directory before leaving
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
meshlab::loadMesh(fileName, pCurrentIOPlugin, prePar, meshList, maskList, QCallBack);
|
||||
}
|
||||
catch(const MLException& e) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Opening Failure"),
|
||||
"While opening: " + fileName + "\n\n" + e.what());
|
||||
meshDoc()->setBusy(false);
|
||||
QDir::setCurrent(origDir); // undo the change of directory before leaving
|
||||
return false;
|
||||
}
|
||||
|
||||
//std::cout << "Opened mesh: in " << tm.elapsed() << " secs\n";
|
||||
// After opening the mesh lets ask to the io plugin if this format
|
||||
// requires some optional, or userdriven post-opening processing.
|
||||
// and in that case ask for the required parameters and then
|
||||
// ask to the plugin to perform that processing
|
||||
//RichParameterSet par;
|
||||
//pCurrentIOPlugin->initOpenParameter(extension, *mm, par);
|
||||
//pCurrentIOPlugin->applyOpenParameter(extension, *mm, par);
|
||||
|
||||
QString err = pCurrentIOPlugin->warningMessageString();
|
||||
if (!err.isEmpty())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Opening Problems"), QString("While opening: '%1'\n\n").arg(fileName)+ err);
|
||||
}
|
||||
|
||||
saveRecentFileList(fileName);
|
||||
|
||||
auto itmesh = meshList.begin();
|
||||
auto itmask = maskList.begin();
|
||||
for (unsigned int i = 0; i < meshList.size(); ++i){
|
||||
MeshModel* mm = *itmesh;
|
||||
int mask = *itmask;
|
||||
|
||||
if (!(mm->cm.textures.empty()))
|
||||
updateTexture(mm->id());
|
||||
|
||||
// In case of polygonal meshes the normal should be updated accordingly
|
||||
if( mask & vcg::tri::io::Mask::IOM_BITPOLYGONAL)
|
||||
{
|
||||
mm->updateDataMask(MeshModel::MM_POLYGONAL); // just to be sure. Hopefully it should be done in the plugin...
|
||||
int degNum = tri::Clean<CMeshO>::RemoveDegenerateFace(mm->cm);
|
||||
if(degNum)
|
||||
GLA()->Logf(0,"Warning model contains %i degenerate faces. Removed them.",degNum);
|
||||
mm->updateDataMask(MeshModel::MM_FACEFACETOPO);
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerBitQuadFaceNormalized(mm->cm);
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerVertexFromCurrentFaceNormal(mm->cm);
|
||||
} // standard case
|
||||
else
|
||||
{
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerFaceNormalized(mm->cm);
|
||||
if(!( mask & vcg::tri::io::Mask::IOM_VERTNORMAL) )
|
||||
vcg::tri::UpdateNormal<CMeshO>::PerVertexAngleWeighted(mm->cm);
|
||||
}
|
||||
|
||||
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm); // updates bounding box
|
||||
if(mm->cm.fn==0 && mm->cm.en==0)
|
||||
{
|
||||
if(mask & vcg::tri::io::Mask::IOM_VERTNORMAL)
|
||||
mm->updateDataMask(MeshModel::MM_VERTNORMAL);
|
||||
}
|
||||
|
||||
if(mm->cm.fn==0 && mm->cm.en>0)
|
||||
{
|
||||
if (mask & vcg::tri::io::Mask::IOM_VERTNORMAL)
|
||||
mm->updateDataMask(MeshModel::MM_VERTNORMAL);
|
||||
}
|
||||
|
||||
updateMenus();
|
||||
int delVertNum = vcg::tri::Clean<CMeshO>::RemoveDegenerateVertex(mm->cm);
|
||||
int delFaceNum = vcg::tri::Clean<CMeshO>::RemoveDegenerateFace(mm->cm);
|
||||
tri::Allocator<CMeshO>::CompactEveryVector(mm->cm);
|
||||
if(delVertNum>0 || delFaceNum>0 )
|
||||
QMessageBox::warning(this, "MeshLab Warning", QString("Warning mesh contains %1 vertices with NAN coords and %2 degenerated faces.\nCorrected.").arg(delVertNum).arg(delFaceNum) );
|
||||
mm->cm.Tr = mtr;
|
||||
|
||||
computeRenderingDataOnLoading(mm,isareload, rendOpt);
|
||||
++itmesh;
|
||||
++itmask;
|
||||
}
|
||||
|
||||
updateLayerDialog();
|
||||
|
||||
meshDoc()->setBusy(false);
|
||||
|
||||
QDir::setCurrent(origDir); // undo the change of directory before leaving
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::computeRenderingDataOnLoading(MeshModel* mm,bool isareload, MLRenderingData* rendOpt)
|
||||
{
|
||||
MultiViewer_Container* mv = currentViewContainer();
|
||||
@ -2145,8 +2014,26 @@ void MainWindow::computeRenderingDataOnLoading(MeshModel* mm,bool isareload, MLR
|
||||
MLSceneGLSharedDataContext* shared = mv->sharedDataContext();
|
||||
if ((shared != NULL) && (mm != NULL))
|
||||
{
|
||||
//count the number of faces contained in the whole meshdocument before the newly inserted mm
|
||||
unsigned int totalSumFaces = 0;
|
||||
bool found = false;
|
||||
for (const MeshModel* m : meshDoc()->meshIterator()){
|
||||
if (!found){
|
||||
if (m != mm){
|
||||
totalSumFaces += mm->cm.FN();
|
||||
}
|
||||
else { //found mm: stop counting
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int minNumberPolFlatShading = mwsettings.minpolygonpersmoothrendering;
|
||||
//if the total number of faces is greater than 5*minpolynumber,
|
||||
//the newly mesh will be set with flat shading
|
||||
if (totalSumFaces > 5 * minNumberPolFlatShading)
|
||||
minNumberPolFlatShading = 0;
|
||||
MLRenderingData defdt;
|
||||
MLPoliciesStandAloneFunctions::suggestedDefaultPerViewRenderingData(mm, defdt,mwsettings.minpolygonpersmoothrendering);
|
||||
MLPoliciesStandAloneFunctions::suggestedDefaultPerViewRenderingData(mm, defdt, minNumberPolFlatShading);
|
||||
if (rendOpt != NULL)
|
||||
defdt = *rendOpt;
|
||||
for (int glarid = 0; glarid < mv->viewerCounter(); ++glarid)
|
||||
@ -2314,8 +2201,7 @@ bool MainWindow::importMesh(QString fileName)
|
||||
}// end foreach file of the input list
|
||||
GLA()->Logf(0,"All files opened in %i msec",allFileTime.elapsed());
|
||||
|
||||
if (_currviewcontainer != NULL)
|
||||
{
|
||||
if (_currviewcontainer != NULL) {
|
||||
_currviewcontainer->resetAllTrackBall();
|
||||
_currviewcontainer->updateAllDecoratorsForAllViewers();
|
||||
}
|
||||
@ -2337,50 +2223,6 @@ void MainWindow::openRecentProj()
|
||||
if (action) openProject(action->data().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* **TODO**: this function assumes that the loaded file will contain just one
|
||||
* mesh.......
|
||||
*/
|
||||
bool MainWindow::loadMeshWithStandardParams(QString& fullPath, MeshModel* mm, const Matrix44m &mtr, bool isreload, MLRenderingData* rendOpt)
|
||||
{
|
||||
if ((meshDoc() == NULL) || (mm == NULL))
|
||||
return false;
|
||||
bool ret = false;
|
||||
if (!mm->isVisible())
|
||||
{
|
||||
mm->clear();
|
||||
mm->setVisible(false);
|
||||
}
|
||||
else
|
||||
mm->clear();
|
||||
QFileInfo fi(fullPath);
|
||||
QString extension = fi.suffix();
|
||||
IOPlugin *pCurrentIOPlugin = PM.inputMeshPlugin(extension);
|
||||
|
||||
if(pCurrentIOPlugin != NULL)
|
||||
{
|
||||
RichParameterList prePar = pCurrentIOPlugin->initPreOpenParameter(extension);
|
||||
prePar.join(currentGlobalParams);
|
||||
|
||||
QElapsedTimer t;t.start();
|
||||
|
||||
std::list<MeshModel*> ml;
|
||||
std::list<int> masks;
|
||||
ml.push_back(mm);
|
||||
bool open = loadMesh(fullPath,pCurrentIOPlugin,ml,masks,prePar,mtr,isreload, rendOpt);
|
||||
if(open)
|
||||
{
|
||||
GLA()->Logf(0, "Opened mesh %s in %i msec", qUtf8Printable(fullPath), t.elapsed());
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
GLA()->Logf(0, "Warning: Mesh %s has not been opened", qUtf8Printable(fullPath));
|
||||
}
|
||||
else
|
||||
GLA()->Logf(0, "Warning: Mesh %s cannot be opened. Your MeshLab version has not plugin to read %s file format", qUtf8Printable(fullPath), qUtf8Printable(extension));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MainWindow::reloadAllMesh()
|
||||
{
|
||||
// Discards changes and reloads current file
|
||||
@ -2482,7 +2324,7 @@ bool MainWindow::exportMesh(QString fileName,MeshModel* mod,const bool saveAllPo
|
||||
mod->setMeshModified(false);
|
||||
QString laylabel = "Save \"" + mod->label() + "\" Layer";
|
||||
QFileDialog* saveDialog = new QFileDialog(this,laylabel, fi.absolutePath());
|
||||
saveDialog->setOption(QFileDialog::DontUseNativeDialog);
|
||||
//saveDialog->setOption(QFileDialog::DontUseNativeDialog);
|
||||
saveDialog->setNameFilters(suffixList);
|
||||
saveDialog->setAcceptMode(QFileDialog::AcceptSave);
|
||||
saveDialog->setFileMode(QFileDialog::AnyFile);
|
||||
@ -2540,7 +2382,8 @@ bool MainWindow::exportMesh(QString fileName,MeshModel* mod,const bool saveAllPo
|
||||
RichParameterList savePar = pCurrentIOPlugin->initSaveParameter(extension,*(mod));
|
||||
|
||||
SaveMeshAttributesDialog maskDialog(this, mod, capability, defaultBits, savePar, this->GLA());
|
||||
int quality = 66;
|
||||
int quality = -1;
|
||||
bool saveTextures = true;
|
||||
if (!saveAllPossibleAttributes)
|
||||
maskDialog.exec();
|
||||
else {
|
||||
@ -2552,13 +2395,17 @@ bool MainWindow::exportMesh(QString fileName,MeshModel* mod,const bool saveAllPo
|
||||
int mask = maskDialog.getNewMask();
|
||||
savePar = maskDialog.getNewAdditionalSaveParameters();
|
||||
quality = maskDialog.getTextureQuality();
|
||||
std::vector<std::string> textureNames = maskDialog.getTextureNames();
|
||||
saveTextures = maskDialog.saveTextures();
|
||||
|
||||
for (unsigned int i = 0; i < mod->cm.textures.size(); ++i){
|
||||
if (textureNames[i].find('.') == std::string::npos){
|
||||
textureNames[i] += ".png";
|
||||
if (!saveTextures){
|
||||
std::vector<std::string> textureNames = maskDialog.getTextureNames();
|
||||
|
||||
for (unsigned int i = 0; i < mod->cm.textures.size(); ++i){
|
||||
if (textureNames[i].find('.') == std::string::npos){
|
||||
textureNames[i] += ".png";
|
||||
}
|
||||
mod->changeTextureName(mod->cm.textures[i], textureNames[i]);
|
||||
}
|
||||
mod->changeTextureName(mod->cm.textures[i], textureNames[i]);
|
||||
}
|
||||
if (!saveAllPossibleAttributes) {
|
||||
maskDialog.close();
|
||||
@ -2576,7 +2423,8 @@ bool MainWindow::exportMesh(QString fileName,MeshModel* mod,const bool saveAllPo
|
||||
try {
|
||||
pCurrentIOPlugin->save(extension, fileName, *mod ,mask,savePar,QCallBack);
|
||||
QFileInfo finfo(fileName);
|
||||
mod->saveTextures(finfo.absolutePath(), quality, &meshDoc()->Log, QCallBack);
|
||||
if (saveTextures)
|
||||
mod->saveTextures(finfo.absolutePath(), quality, &meshDoc()->Log, QCallBack);
|
||||
GLA()->Logf(GLLogStream::SYSTEM, "Saved Mesh %s in %i msec", qUtf8Printable(fileName), tt.elapsed());
|
||||
mod->setFileName(fileName);
|
||||
QSettings settings;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user