2016-08-31 18:20:59 +00:00

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();
}