mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-18 02:24:38 +00:00
370 lines
14 KiB
C++
370 lines
14 KiB
C++
/****************************************************************************
|
|
* MeshLab o o *
|
|
* An extendible mesh processor o o *
|
|
* _ O _ *
|
|
* Copyright(C) 2005, 2009 \/)\/ *
|
|
* Visual Computing Lab /\/| *
|
|
* ISTI - Italian National Research Council | *
|
|
* \ *
|
|
* All rights reserved. *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
* for more details. *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
#include "shaderDialog.h"
|
|
#include <QTextStream>
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QColor>
|
|
#include <QLineEdit>
|
|
#include <QColorDialog>
|
|
#include <QGLWidget>
|
|
#include <QCheckBox>
|
|
#include <QPushButton>
|
|
|
|
#define DECFACTOR 100000.0f
|
|
|
|
using namespace vcg;
|
|
|
|
ShaderDialog::ShaderDialog(ShaderInfo *sInfo, QGLWidget* gla, QWidget *parent)
|
|
: QDockWidget(parent),usevertexcolor(false)
|
|
{
|
|
ui.setupUi(this);
|
|
this->setWidget(ui.frame);
|
|
this->setFeatures(QDockWidget::AllDockWidgetFeatures);
|
|
this->setAllowedAreas(Qt::LeftDockWidgetArea);
|
|
this->setFloating(true);
|
|
|
|
shaderInfo = sInfo;
|
|
glarea = gla;
|
|
colorSignalMapper = new QSignalMapper(this);
|
|
valueSignalMapper = new QSignalMapper(this);
|
|
|
|
QGridLayout * qgrid = new QGridLayout(ui.uvTab);
|
|
qgrid->setColumnMinimumWidth(0, 45);
|
|
qgrid->setColumnMinimumWidth(1, 40);
|
|
qgrid->setColumnMinimumWidth(2, 40);
|
|
qgrid->setColumnMinimumWidth(3, 40);
|
|
|
|
/*QLabel *perVertexColorLabel = new QLabel(this);
|
|
perVertexColorLabel->setText("Use PerVertex Color");
|
|
QCheckBox *perVertexColorCBox = new QCheckBox(this);
|
|
connect(perVertexColorCBox, SIGNAL(stateChanged(int)), this, SLOT(setColorMode(int)));
|
|
|
|
qgrid->addWidget(perVertexColorLabel, 0, 0);
|
|
qgrid->addWidget(perVertexColorCBox, 0, 1);*/
|
|
|
|
int row=0;
|
|
std::map<QString, UniformVariable>::iterator i;
|
|
for (i = shaderInfo->uniformVars.begin(); i != shaderInfo->uniformVars.end(); ++i) {
|
|
|
|
QLabel *varNameLabel = new QLabel(this);
|
|
varNameLabel->setObjectName(i->first+"_name");
|
|
varNameLabel->setText(i->first);
|
|
|
|
qgrid->addWidget(varNameLabel, row, 0);
|
|
|
|
int varNum = UniformVariable::getVarsNumber(i->second.type);
|
|
|
|
switch (i->second.widget) {
|
|
|
|
case WIDGET_NONE: {
|
|
for (int j=0;j<varNum;++j) {
|
|
QLineEdit *qline = new QLineEdit(this);
|
|
qline->setAlignment(Qt::AlignRight);
|
|
qline->setObjectName(tr("%1%2").arg(i->first).arg(j));
|
|
if (i->second.type == SINGLE_INT) {
|
|
qline->setText(tr("%1").arg(i->second.ival[j]));
|
|
|
|
} else {
|
|
qline->setText(tr("%1").arg(i->second.fval[j]));
|
|
|
|
}
|
|
|
|
connect(qline, SIGNAL(textChanged(QString)), valueSignalMapper, SLOT(map()));
|
|
valueSignalMapper->setMapping(qline,tr("%1%2").arg(i->first).arg(j));
|
|
lineEdits[tr("%1%2").arg(i->first).arg(j)]=qline;
|
|
|
|
qgrid->addWidget(qline, row, j+1);
|
|
}
|
|
} break;
|
|
case WIDGET_COLOR : {
|
|
|
|
QPushButton * colorButton = new QPushButton(this);
|
|
colorButton->setText("Change");
|
|
connect(colorButton, SIGNAL(clicked()), colorSignalMapper, SLOT(map()));
|
|
colorSignalMapper->setMapping(colorButton,i->first);
|
|
|
|
qgrid->addWidget(colorButton, row, 1);
|
|
|
|
|
|
} break;
|
|
case WIDGET_SLIDER : {
|
|
for (int j=0;j<varNum;++j) {
|
|
QSlider *qslider = new QSlider(this);
|
|
qslider->setTickPosition(QSlider::NoTicks);
|
|
qslider->setOrientation(Qt::Horizontal);
|
|
qslider->setObjectName(tr("%1%2").arg(i->first).arg(j));
|
|
if (i->second.type == SINGLE_INT) {
|
|
qslider->setTickInterval(i->second.step);
|
|
qslider->setRange(i->second.min, i->second.max);
|
|
qslider->setValue(i->second.ival[j]);
|
|
} else {
|
|
qslider->setTickInterval(i->second.step*DECFACTOR);
|
|
qslider->setRange(i->second.min*DECFACTOR, i->second.max*DECFACTOR);
|
|
qslider->setValue(i->second.fval[j]*DECFACTOR);
|
|
}
|
|
connect(qslider, SIGNAL(valueChanged(int)), valueSignalMapper, SLOT(map()));
|
|
valueSignalMapper->setMapping(qslider,tr("%1%2").arg(i->first).arg(j));
|
|
|
|
sliders[tr("%1%2").arg(i->first).arg(j)]=qslider;
|
|
|
|
qgrid->addWidget(qslider, row, j+1);
|
|
|
|
}
|
|
} break;
|
|
}
|
|
++row;
|
|
}
|
|
|
|
|
|
connect(colorSignalMapper, SIGNAL(mapped(const QString &)), this, SLOT(setColorValue(const QString &)));
|
|
connect(valueSignalMapper, SIGNAL(mapped(const QString &)), this, SLOT(valuesChanged(const QString &)));
|
|
|
|
//Texture Tab Section
|
|
|
|
if (shaderInfo->textureInfo.size() > 0) {
|
|
textLineSignalMapper = new QSignalMapper(this);
|
|
textButtonSignalMapper = new QSignalMapper(this);
|
|
|
|
|
|
QGridLayout * qgridTexTab = new QGridLayout(ui.textureTab);
|
|
qgridTexTab->setColumnMinimumWidth(0, 45);
|
|
qgridTexTab->setColumnMinimumWidth(1, 40);
|
|
|
|
row = 0;
|
|
std::vector<TextureInfo>::iterator textIter;
|
|
for (textIter = shaderInfo->textureInfo.begin(); textIter != shaderInfo->textureInfo.end(); ++textIter) {
|
|
QLabel *textNameLabel = new QLabel(this);
|
|
QLineEdit *textValueEdit = new QLineEdit(this);
|
|
QPushButton * textButton = new QPushButton(this);
|
|
textButton->setText("Browse");
|
|
textNameLabel->setText(tr("Texture Unit %1:").arg(row));
|
|
textValueEdit->setText(textIter->path);
|
|
qgridTexTab->addWidget(textNameLabel, row, 0);
|
|
qgridTexTab->addWidget(textValueEdit, row, 1);
|
|
qgridTexTab->addWidget(textButton, row, 2);
|
|
|
|
|
|
connect(textValueEdit, SIGNAL(editingFinished()), textLineSignalMapper, SLOT(map()));
|
|
textLineSignalMapper->setMapping(textValueEdit,row);
|
|
|
|
connect(textButton, SIGNAL(clicked()), textButtonSignalMapper, SLOT(map()));
|
|
textButtonSignalMapper->setMapping(textButton,row);
|
|
|
|
textLineEdits.push_back(textValueEdit);
|
|
++row;
|
|
}
|
|
|
|
connect(textLineSignalMapper, SIGNAL(mapped(int)), this, SLOT(changeTexturePath(int)));
|
|
connect(textButtonSignalMapper, SIGNAL(mapped(int)), this, SLOT(browseTexturePath(int)));
|
|
}
|
|
|
|
//OpenGL Status Tab Section
|
|
|
|
QGridLayout * qgridGlStatus = new QGridLayout(ui.glTab);
|
|
qgridGlStatus->setColumnMinimumWidth(0, 45);
|
|
qgridGlStatus->setColumnMinimumWidth(1, 40);
|
|
|
|
row = 0;
|
|
std::map<int, QString>::iterator glIterator;
|
|
for (glIterator = shaderInfo->glStatus.begin(); glIterator != shaderInfo->glStatus.end(); ++glIterator) {
|
|
QLabel *glVarLabel = new QLabel(this);
|
|
QLabel *glValueLabel = new QLabel(this);
|
|
|
|
|
|
switch (glIterator->first) {
|
|
case SHADE: glVarLabel->setText("glShadeModel"); glValueLabel->setText(glIterator->second); ++row; break;
|
|
case ALPHA_TEST: glVarLabel->setText("GL_ALPHA_TEST"); glValueLabel->setText(glIterator->second); ++row; break;
|
|
case ALPHA_FUNC: glVarLabel->setText("glAlphaFunc"); glValueLabel->setText(glIterator->second + ", " + shaderInfo->glStatus[ALPHA_CLAMP]); ++row; break;
|
|
//case ALPHA_CLAMP: used in ALPHA_FUNC
|
|
case BLENDING: glVarLabel->setText("GL_BLEND"); glValueLabel->setText(glIterator->second); ++row; break;
|
|
case BLEND_FUNC_SRC: glVarLabel->setText("glBlendFunc"); glValueLabel->setText(glIterator->second + ", " + shaderInfo->glStatus[BLEND_FUNC_SRC]); ++row; break;
|
|
//case BLEND_FUNC_DST: used in BLEND_FUNC_SRC
|
|
case BLEND_EQUATION: glVarLabel->setText("glBlendEquation"); glValueLabel->setText(glIterator->second); ++row; break;
|
|
case DEPTH_TEST: glVarLabel->setText("GL_DEPTH_TEST"); glValueLabel->setText(glIterator->second); ++row; break;
|
|
case DEPTH_FUNC: glVarLabel->setText("glDepthFunc"); glValueLabel->setText(glIterator->second); ++row; break;
|
|
//case CLAMP_NEAR:
|
|
//case CLAMP_FAR:
|
|
case CLEAR_COLOR_R: glVarLabel->setText("glClearColor"); glValueLabel->setText(glIterator->second + ", " +
|
|
shaderInfo->glStatus[CLEAR_COLOR_G] + ", " +
|
|
shaderInfo->glStatus[CLEAR_COLOR_B] + ", " +
|
|
shaderInfo->glStatus[CLEAR_COLOR_A]); ++row; break;
|
|
//case CLEAR_COLOR_G: used in CLEAR_COLOR_R
|
|
//case CLEAR_COLOR_B: used in CLEAR_COLOR_R
|
|
//case CLEAR_COLOR_A: used in CLEAR_COLOR_R
|
|
}
|
|
|
|
qgridGlStatus->addWidget(glVarLabel, row, 0);
|
|
qgridGlStatus->addWidget(glValueLabel, row, 1);
|
|
|
|
}
|
|
|
|
//Vertex and Fragment Program Tabs Section
|
|
|
|
QFile qf;
|
|
QTextStream ts(&qf);
|
|
|
|
qf.setFileName(shaderInfo->vpFile);
|
|
if (!qf.open(QIODevice::ReadOnly | QIODevice::Text) )
|
|
QMessageBox::critical(this,"Opengl Shader" ,"unable to open file");
|
|
ui.vpTextBrowser->insertPlainText(ts.readAll());
|
|
qf.close();
|
|
|
|
qf.setFileName(shaderInfo->fpFile);
|
|
if (!qf.open(QIODevice::ReadOnly | QIODevice::Text) )
|
|
QMessageBox::critical(this,"Opengl Shader" ,"unable to open file");
|
|
ui.fpTextBrowser->insertPlainText(ts.readAll());
|
|
qf.close();
|
|
|
|
//End of Vertex and Fragment Program Tabs Section
|
|
}
|
|
|
|
ShaderDialog::~ShaderDialog()
|
|
{
|
|
|
|
}
|
|
|
|
void ShaderDialog::setColorValue(const QString &varName)
|
|
{
|
|
QColor old;
|
|
if ( shaderInfo->uniformVars[varName].type == ARRAY_3_FLOAT) {
|
|
old.setRgbF(shaderInfo->uniformVars[varName].fval[0], shaderInfo->uniformVars[varName].fval[1], shaderInfo->uniformVars[varName].fval[2]);
|
|
} else if (shaderInfo->uniformVars[varName].type == ARRAY_4_FLOAT) {
|
|
old.setRgbF(shaderInfo->uniformVars[varName].fval[0], shaderInfo->uniformVars[varName].fval[1], shaderInfo->uniformVars[varName].fval[2], shaderInfo->uniformVars[varName].fval[3]);
|
|
}
|
|
|
|
QColor newColor = QColorDialog::getColor(old, this);
|
|
if (newColor.isValid()) {
|
|
|
|
shaderInfo->uniformVars[varName].fval[0] = newColor.redF();
|
|
shaderInfo->uniformVars[varName].fval[1] = newColor.greenF();
|
|
shaderInfo->uniformVars[varName].fval[2] = newColor.blueF();
|
|
|
|
if (shaderInfo->uniformVars[varName].type == ARRAY_4_FLOAT) {
|
|
|
|
shaderInfo->uniformVars[varName].fval[3] = newColor.alphaF();
|
|
|
|
}
|
|
}
|
|
glarea->update();
|
|
}
|
|
|
|
|
|
void ShaderDialog::valuesChanged(const QString &varNameAndIndex) {
|
|
|
|
|
|
int varIndex = varNameAndIndex[varNameAndIndex.length()-1].digitValue();
|
|
QString varName = varNameAndIndex;
|
|
varName.chop(1);
|
|
|
|
int varWidget = shaderInfo->uniformVars[varName].widget;
|
|
int varType = shaderInfo->uniformVars[varName].type;
|
|
switch (varWidget) {
|
|
case WIDGET_NONE: {
|
|
QLineEdit * qline = lineEdits[varNameAndIndex];
|
|
if (varType == SINGLE_INT) {
|
|
shaderInfo->uniformVars[varName].ival[varIndex] = qline->text().toInt();
|
|
} else {
|
|
shaderInfo->uniformVars[varName].fval[varIndex] = qline->text().toFloat();
|
|
}
|
|
} break;
|
|
case WIDGET_SLIDER: {
|
|
QSlider * qslider = sliders[varNameAndIndex];
|
|
if (varType == SINGLE_INT) {
|
|
shaderInfo->uniformVars[varName].ival[varIndex] = qslider->value();
|
|
} else {
|
|
shaderInfo->uniformVars[varName].fval[varIndex] = qslider->value()/DECFACTOR;
|
|
}
|
|
} break;
|
|
}
|
|
glarea->update();
|
|
|
|
}
|
|
|
|
|
|
void ShaderDialog::setColorMode(int state)
|
|
{
|
|
usevertexcolor = (state == Qt::Checked);
|
|
glarea->update();
|
|
}
|
|
|
|
void ShaderDialog::changeTexturePath(int i) {
|
|
shaderInfo->textureInfo[i].path = textLineEdits[i]->text();
|
|
reloadTexture(i);
|
|
}
|
|
|
|
void ShaderDialog::browseTexturePath(int i) {
|
|
QFileDialog fd(0,"Choose new texture");
|
|
|
|
QDir shadersDir = QDir(qApp->applicationDirPath());
|
|
#if defined(Q_OS_WIN)
|
|
if (shadersDir.dirName() == "debug" || shadersDir.dirName() == "release")
|
|
shadersDir.cdUp();
|
|
#elif defined(Q_OS_MAC)
|
|
if (shadersDir.dirName() == "MacOS") {
|
|
shadersDir.cdUp();
|
|
shadersDir.cdUp();
|
|
shadersDir.cdUp();
|
|
}
|
|
#endif
|
|
shadersDir.cd("textures");
|
|
|
|
fd.setDirectory(shadersDir);
|
|
fd.move(500, 100);
|
|
|
|
QStringList newPath;
|
|
if (fd.exec())
|
|
{
|
|
newPath = fd.selectedFiles();
|
|
textLineEdits[i]->setText(newPath.at(0));
|
|
shaderInfo->textureInfo[i].path = newPath.at(0);
|
|
reloadTexture(i);
|
|
}
|
|
|
|
}
|
|
|
|
void ShaderDialog::reloadTexture(int i) {
|
|
glDeleteTextures( 1, &shaderInfo->textureInfo[i].tId);
|
|
|
|
glEnable(shaderInfo->textureInfo[i].Target);
|
|
QImage img, imgScaled, imgGL;
|
|
img.load(shaderInfo->textureInfo[i].path);
|
|
// image has to be scaled to a 2^n size. We choose the first 2^N <= picture size.
|
|
int bestW=pow(2.0,floor(::log(double(img.width() ))/::log(2.0)));
|
|
int bestH=pow(2.0,floor(::log(double(img.height()))/::log(2.0)));
|
|
imgScaled=img.scaled(bestW,bestH,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
|
|
imgGL=QGLWidget::convertToGLFormat(imgScaled);
|
|
|
|
glGenTextures( 1, &(shaderInfo->textureInfo[i].tId) );
|
|
glBindTexture( shaderInfo->textureInfo[i].Target, shaderInfo->textureInfo[i].tId );
|
|
glTexImage2D( shaderInfo->textureInfo[i].Target, 0, 3, imgGL.width(), imgGL.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, imgGL.bits() );
|
|
glTexParameteri( shaderInfo->textureInfo[i].Target, GL_TEXTURE_MIN_FILTER, shaderInfo->textureInfo[i].MinFilter );
|
|
glTexParameteri( shaderInfo->textureInfo[i].Target, GL_TEXTURE_MAG_FILTER, shaderInfo->textureInfo[i].MagFilter );
|
|
glTexParameteri( shaderInfo->textureInfo[i].Target, GL_TEXTURE_WRAP_S, shaderInfo->textureInfo[i].WrapS );
|
|
glTexParameteri( shaderInfo->textureInfo[i].Target, GL_TEXTURE_WRAP_T, shaderInfo->textureInfo[i].WrapT );
|
|
glTexParameteri( shaderInfo->textureInfo[i].Target, GL_TEXTURE_WRAP_R, shaderInfo->textureInfo[i].WrapR );
|
|
|
|
glarea->update();
|
|
}
|