mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-13 16:14:38 +00:00
323 lines
9.2 KiB
C++
323 lines
9.2 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 <common/interfaces.h>
|
|
#include <meshlab/glarea.h>
|
|
#include "edittexture.h"
|
|
#include "renderarea.h"
|
|
#include <wrap/gl/pick.h>
|
|
#include <wrap/gl/picking.h>
|
|
|
|
#include <vcg/complex/algorithms/clean.h>
|
|
#include <QDockWidget>
|
|
|
|
using namespace vcg;
|
|
|
|
EditTexturePlugin::EditTexturePlugin()
|
|
{
|
|
isDragging = false;
|
|
widget = 0;
|
|
qFont.setFamily("Helvetica");
|
|
qFont.setPixelSize(14);
|
|
}
|
|
|
|
EditTexturePlugin::~EditTexturePlugin()
|
|
{
|
|
// Delete the tool widget
|
|
if (widget != 0)
|
|
{
|
|
delete widget;
|
|
widget = 0;
|
|
}
|
|
}
|
|
|
|
const QString EditTexturePlugin::Info()
|
|
{
|
|
return tr("Edit texture coordinates of the selected area");
|
|
}
|
|
|
|
void EditTexturePlugin::mousePressEvent(QMouseEvent * event, MeshModel &m, GLArea * gla)
|
|
{
|
|
isDragging = true;
|
|
|
|
if(event->modifiers() == Qt::ControlModifier) selMode = SMAdd;
|
|
else if(event->modifiers() == Qt::ShiftModifier) selMode = SMSub;
|
|
else selMode = SMClear;
|
|
// Change the appearance of the cursor
|
|
switch(selMode)
|
|
{
|
|
case SMAdd: // CTRL + Mouse
|
|
gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus.png"),1,1));
|
|
break;
|
|
case SMSub: // SHIFT + Mouse
|
|
gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus.png"),1,1));
|
|
break;
|
|
case SMClear: // Mouse
|
|
gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"),1,1));
|
|
for (unsigned i = 0; i < FaceSel.size(); i++) FaceSel[i]->ClearS();
|
|
FaceSel.clear();
|
|
break;
|
|
}
|
|
if(event->modifiers() == Qt::ControlModifier || event->modifiers() == Qt::ShiftModifier )
|
|
{
|
|
CMeshO::FaceIterator fi;
|
|
for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
|
|
if(!(*fi).IsD() && (*fi).IsS()) FaceSel.push_back(&*fi);
|
|
}
|
|
|
|
start = event->pos();
|
|
cur = start;
|
|
gla->update();
|
|
return;
|
|
}
|
|
|
|
void EditTexturePlugin::mouseMoveEvent(QMouseEvent * event, MeshModel &/*m*/, GLArea * gla)
|
|
{
|
|
prev = cur;
|
|
cur = event->pos();
|
|
/*int curT;
|
|
static int lastRendering;
|
|
if (isDragging)
|
|
{
|
|
// The user is selecting an area: management of the update
|
|
lastRendering = clock();
|
|
curT = clock();
|
|
if(gla->lastRenderingTime() < 50 || (curT - lastRendering) > 1000 )
|
|
{
|
|
lastRendering = curT;
|
|
gla->update();
|
|
}
|
|
else
|
|
{
|
|
gla->makeCurrent();
|
|
glDrawBuffer(GL_FRONT);
|
|
DrawXORRect(gla);
|
|
glDrawBuffer(GL_BACK);
|
|
glFlush();
|
|
}
|
|
}*/
|
|
if(gla->lastRenderingTime() < 200 )
|
|
{
|
|
gla->update();
|
|
}
|
|
else
|
|
{
|
|
gla->makeCurrent();
|
|
glDrawBuffer(GL_FRONT);
|
|
DrawXORRect(gla);
|
|
glDrawBuffer(GL_BACK);
|
|
glFlush();
|
|
}
|
|
}
|
|
|
|
void EditTexturePlugin::mouseReleaseEvent(QMouseEvent * event, MeshModel &/*m*/, GLArea * gla)
|
|
{
|
|
prev = cur;
|
|
cur = event->pos();
|
|
gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"),1,1));
|
|
if (isDragging)
|
|
{
|
|
widget->SelectFromModel();
|
|
isDragging = false;
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
void EditTexturePlugin::Decorate(MeshModel &m, GLArea *gla)
|
|
{
|
|
if (isDragging)
|
|
{
|
|
QPoint mid, wid;
|
|
vector<CMeshO::FacePointer> NewFaceSel;
|
|
vector<CMeshO::FacePointer>::iterator fpi;
|
|
CMeshO::FaceIterator fi;
|
|
|
|
DrawXORRect(gla);
|
|
mid = (start + cur)/2;
|
|
mid.setY(gla->height() - mid.y());
|
|
wid = (start - cur);
|
|
if(wid.x()<0) wid.setX(-wid.x());
|
|
if(wid.y()<0) wid.setY(-wid.y());
|
|
|
|
for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
|
|
if(!(*fi).IsD()) (*fi).ClearS();
|
|
|
|
glPushMatrix();
|
|
glMultMatrix(m.cm.Tr);
|
|
GLPickTri<CMeshO>::PickFace(mid.x(), mid.y(), m.cm, NewFaceSel, wid.x(), wid.y());
|
|
glPopMatrix();
|
|
|
|
switch(selMode)
|
|
{
|
|
case SMSub:
|
|
for(fpi = FaceSel.begin(); fpi != FaceSel.end(); ++fpi)
|
|
(*fpi)->SetS();
|
|
for(fpi = NewFaceSel.begin(); fpi != NewFaceSel.end(); ++fpi)
|
|
(*fpi)->ClearS();
|
|
break;
|
|
case SMAdd:
|
|
for(fpi = FaceSel.begin(); fpi != FaceSel.end(); ++fpi)
|
|
(*fpi)->SetS();
|
|
case SMClear:
|
|
for(fpi = NewFaceSel.begin(); fpi != NewFaceSel.end(); ++fpi)
|
|
(*fpi)->SetS();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool EditTexturePlugin::StartEdit(MeshModel &m, GLArea *gla )
|
|
{
|
|
// Set up the model
|
|
//m.cm.face.EnableFFAdjacency();
|
|
m.updateDataMask(MeshModel::MM_FACEFACETOPO);
|
|
|
|
if (m.cm.textures.size() == 0)
|
|
{
|
|
QMessageBox::warning(gla->window(), "Texture Parametrization Tool",
|
|
"Sorry, this mesh has no texture.",
|
|
QMessageBox::Ok, QMessageBox::Ok);
|
|
return false;
|
|
}
|
|
|
|
if (vcg::tri::HasPerWedgeTexCoord(m.cm))
|
|
{
|
|
vcg::tri::UpdateTopology<CMeshO>::FaceFaceFromTexCoord(m.cm);
|
|
if(vcg::tri::Clean<CMeshO>::HasConsistentPerWedgeTexCoord(m.cm) && !HasCollapsedTextCoords(m)) degenerate = false;
|
|
else
|
|
{
|
|
this->Log(GLLogStream::WARNING,"This mesh has a degenerated texture parametrization!");
|
|
degenerate = true;
|
|
}
|
|
}
|
|
|
|
FaceSel.clear();
|
|
CMeshO::FaceIterator ff;
|
|
for(ff = m.cm.face.begin(); ff != m.cm.face.end(); ++ff)
|
|
if(!(*ff).IsD() && (*ff).IsS()) FaceSel.push_back(&*ff);
|
|
|
|
CMeshO::FaceIterator fi;
|
|
for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) (*fi).ClearS();
|
|
|
|
gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"),1,1));
|
|
|
|
connect(this, SIGNAL(setSelectionRendering(bool)),gla,SLOT(setSelectionRendering(bool)));
|
|
setSelectionRendering(true);
|
|
|
|
// Create an instance of the interface
|
|
if (widget == 0)
|
|
{
|
|
widget = new TextureEditor(gla->window(), &m, gla, degenerate);
|
|
dock = new QDockWidget(gla->window());
|
|
dock->setAllowedAreas(Qt::NoDockWidgetArea);
|
|
dock->setWidget(widget);
|
|
QPoint p = gla->window()->mapToGlobal(QPoint(0,0));
|
|
dock->setGeometry(-5+p.x()+gla->window()->width()-widget->width(),p.y(),widget->width(),widget->height());
|
|
dock->setFloating(true);
|
|
}
|
|
dock->setVisible(true);
|
|
dock->layout()->update();
|
|
|
|
// Initialize the texture using the intere model
|
|
InitTexture(m);
|
|
|
|
gla->update();
|
|
return true;
|
|
}
|
|
|
|
void EditTexturePlugin::EndEdit(MeshModel &m , GLArea * )
|
|
{
|
|
// Delete the widget
|
|
for (unsigned i = 0; i < m.cm.face.size(); i++) m.cm.face[i].ClearS();
|
|
if (widget != 0)
|
|
{
|
|
delete widget;
|
|
delete dock;
|
|
widget = 0;
|
|
dock = 0;
|
|
}
|
|
}
|
|
|
|
void EditTexturePlugin::DrawXORRect(GLArea *gla)
|
|
{
|
|
// Draw the rectangle of the selection area
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0, gla->width(), gla->height(),0,-1,1);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glPushAttrib(GL_ENABLE_BIT);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_COLOR_LOGIC_OP);
|
|
glLogicOp(GL_XOR);
|
|
glColor3f(1,1,1);
|
|
|
|
glBegin(GL_LINE_LOOP);
|
|
glVertex2f(start.x(),start.y());
|
|
glVertex2f(cur.x(),start.y());
|
|
glVertex2f(cur.x(),cur.y());
|
|
glVertex2f(start.x(),cur.y());
|
|
glEnd();
|
|
|
|
glDisable(GL_LOGIC_OP);
|
|
glPopAttrib();
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
|
|
void EditTexturePlugin::InitTexture(MeshModel &m)
|
|
{
|
|
// Get the textures name and add the tab
|
|
if (m.cm.textures.size() > 0)
|
|
{
|
|
for(unsigned i = 0; i < m.cm.textures.size(); i++)
|
|
widget->AddRenderArea(m.cm.textures[i].c_str(), &m, i);
|
|
}
|
|
else widget->AddEmptyRenderArea();
|
|
}
|
|
|
|
|
|
// DA METTERE IN Clean.h
|
|
/**
|
|
Check if the parametrization is valid
|
|
*/
|
|
bool EditTexturePlugin::HasCollapsedTextCoords(MeshModel &m)
|
|
{
|
|
if(!HasPerWedgeTexCoord(m.cm)) return true;
|
|
for (CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
|
|
{
|
|
if(!(*fi).IsD())
|
|
{
|
|
if( (*fi).WT(0).P() == (*fi).WT(1).P() || (*fi).WT(0).P() == (*fi).WT(2).P() || (*fi).WT(1).P() == (*fi).WT(2).P())
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|