1 /****************************************************************************
2 * MeshLab                                                           o o     *
3 * An extendible mesh processor                                    o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2005, 2009                                          \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 #include <common/interfaces.h>
25 #include <meshlab/glarea.h>
26 #include "edittexture.h"
27 #include "renderarea.h"
28 #include <wrap/gl/pick.h>
29 #include <wrap/gl/picking.h>
30 
31 #include <vcg/complex/algorithms/clean.h>
32 #include <QDockWidget>
33 
34 using namespace vcg;
35 
EditTexturePlugin()36 EditTexturePlugin::EditTexturePlugin()
37 {
38 	isDragging = false;
39 	widget = 0;
40 	qFont.setFamily("Helvetica");
41 	qFont.setPixelSize(14);
42 }
43 
~EditTexturePlugin()44 EditTexturePlugin::~EditTexturePlugin()
45 {
46 	// Delete the tool widget
47 	if (widget != 0)
48 	{
49 		delete widget;
50 		widget = 0;
51 	}
52 }
53 
Info()54 const QString EditTexturePlugin::Info()
55 {
56 	return tr("Edit texture coordinates of the selected area");
57 }
58 
mousePressEvent(QMouseEvent * event,MeshModel & m,GLArea * gla)59 void EditTexturePlugin::mousePressEvent(QMouseEvent * event, MeshModel &m, GLArea * gla)
60 {
61 	isDragging = true;
62 
63     if(event->modifiers() == Qt::ControlModifier) selMode = SMAdd;
64     else if(event->modifiers() == Qt::ShiftModifier) selMode = SMSub;
65     else selMode = SMClear;
66     // Change the appearance of the cursor
67     switch(selMode)
68     {
69         case SMAdd:	// CTRL + Mouse
70             gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus.png"),1,1));
71             break;
72         case SMSub: // SHIFT + Mouse
73             gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus.png"),1,1));
74             break;
75         case SMClear: // Mouse
76             gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"),1,1));
77             for (unsigned i = 0; i < FaceSel.size(); i++) FaceSel[i]->ClearS();
78             FaceSel.clear();
79             break;
80     }
81     if(event->modifiers() == Qt::ControlModifier || event->modifiers() == Qt::ShiftModifier )
82     {
83         CMeshO::FaceIterator fi;
84         for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
85             if(!(*fi).IsD() && (*fi).IsS()) FaceSel.push_back(&*fi);
86     }
87 
88     start = event->pos();
89     cur = start;
90     gla->update();
91     return;
92 }
93 
mouseMoveEvent(QMouseEvent * event,MeshModel &,GLArea * gla)94 void EditTexturePlugin::mouseMoveEvent(QMouseEvent * event, MeshModel &/*m*/, GLArea * gla)
95 {
96     prev = cur;
97     cur = event->pos();
98     /*int curT;
99     static int lastRendering;
100     if (isDragging)
101     {
102         // The user is selecting an area: management of the update
103         lastRendering = clock();
104         curT = clock();
105         if(gla->lastRenderingTime() < 50 || (curT - lastRendering) > 1000 )
106         {
107             lastRendering = curT;
108             gla->update();
109         }
110         else
111         {
112             gla->makeCurrent();
113             glDrawBuffer(GL_FRONT);
114             DrawXORRect(gla);
115             glDrawBuffer(GL_BACK);
116             glFlush();
117         }
118     }*/
119     if(gla->lastRenderingTime() < 200 )
120     {
121         gla->update();
122     }
123     else
124     {
125         gla->makeCurrent();
126         glDrawBuffer(GL_FRONT);
127         DrawXORRect(gla);
128         glDrawBuffer(GL_BACK);
129         glFlush();
130     }
131 }
132 
mouseReleaseEvent(QMouseEvent * event,MeshModel &,GLArea * gla)133 void EditTexturePlugin::mouseReleaseEvent(QMouseEvent * event, MeshModel &/*m*/, GLArea * gla)
134 {
135     prev = cur;
136     cur = event->pos();
137     gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"),1,1));
138     if (isDragging)
139     {
140         widget->SelectFromModel();
141         isDragging = false;
142     }
143     gla->update();
144 }
145 
Decorate(MeshModel & m,GLArea * gla)146 void EditTexturePlugin::Decorate(MeshModel &m, GLArea *gla)
147 {
148 	if (isDragging)
149 	{
150 		QPoint mid, wid;
151 		vector<CMeshO::FacePointer> NewFaceSel;
152 		vector<CMeshO::FacePointer>::iterator fpi;
153 		CMeshO::FaceIterator fi;
154 
155 		DrawXORRect(gla);
156 		mid = (start + cur)/2;
157 		mid.setY(gla->height() - mid.y());
158 		wid = (start - cur);
159 		if(wid.x()<0) wid.setX(-wid.x());
160 		if(wid.y()<0) wid.setY(-wid.y());
161 
162 		for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
163 			if(!(*fi).IsD()) (*fi).ClearS();
164 
165 		glPushMatrix();
166 		glMultMatrix(m.cm.Tr);
167 		GLPickTri<CMeshO>::PickFace(mid.x(), mid.y(), m.cm, NewFaceSel, wid.x(), wid.y());
168 		glPopMatrix();
169 
170 		switch(selMode)
171 		{
172 			case SMSub:
173 				for(fpi = FaceSel.begin(); fpi != FaceSel.end(); ++fpi)
174 					(*fpi)->SetS();
175 				for(fpi = NewFaceSel.begin(); fpi != NewFaceSel.end(); ++fpi)
176 					(*fpi)->ClearS();
177 				break;
178 			case SMAdd:
179 				for(fpi = FaceSel.begin(); fpi != FaceSel.end(); ++fpi)
180 					(*fpi)->SetS();
181 			case SMClear:
182 				for(fpi = NewFaceSel.begin(); fpi != NewFaceSel.end(); ++fpi)
183 					(*fpi)->SetS();
184 				break;
185 		}
186 	}
187 }
188 
StartEdit(MeshModel & m,GLArea * gla)189 bool EditTexturePlugin::StartEdit(MeshModel &m, GLArea *gla )
190 {
191 	// Set up the model
192 	//m.cm.face.EnableFFAdjacency();
193   m.updateDataMask(MeshModel::MM_FACEFACETOPO);
194 
195 	if (m.cm.textures.size() == 0)
196 	{
197 		QMessageBox::warning(gla->window(), "Texture Parametrization Tool",
198 			"Sorry, this mesh has no texture.",
199 			QMessageBox::Ok, QMessageBox::Ok);
200 		return false;
201 	}
202 
203 	if (vcg::tri::HasPerWedgeTexCoord(m.cm))
204 	{
205 		vcg::tri::UpdateTopology<CMeshO>::FaceFaceFromTexCoord(m.cm);
206 		if(vcg::tri::Clean<CMeshO>::HasConsistentPerWedgeTexCoord(m.cm) && !HasCollapsedTextCoords(m)) degenerate = false;
207 		else
208 		{
209 			this->Log(GLLogStream::WARNING,"This mesh has a degenerated texture parametrization!");
210 			degenerate = true;
211 		}
212 	}
213 
214 	FaceSel.clear();
215 	CMeshO::FaceIterator ff;
216 	for(ff = m.cm.face.begin(); ff != m.cm.face.end(); ++ff)
217 		if(!(*ff).IsD() && (*ff).IsS()) FaceSel.push_back(&*ff);
218 
219 	CMeshO::FaceIterator fi;
220 	for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) (*fi).ClearS();
221 
222 	gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"),1,1));
223 
224 	connect(this, SIGNAL(setSelectionRendering(bool)),gla,SLOT(setSelectionRendering(bool)));
225 	setSelectionRendering(true);
226 
227 	// Create an instance of the interface
228 	if (widget == 0)
229 	{
230 		widget = new TextureEditor(gla->window(), &m, gla, degenerate);
231 		dock = new QDockWidget(gla->window());
232 		dock->setAllowedAreas(Qt::NoDockWidgetArea);
233 		dock->setWidget(widget);
234 		QPoint p = gla->window()->mapToGlobal(QPoint(0,0));
235 		dock->setGeometry(-5+p.x()+gla->window()->width()-widget->width(),p.y(),widget->width(),widget->height());
236 		dock->setFloating(true);
237 	}
238 	dock->setVisible(true);
239 	dock->layout()->update();
240 
241 	// Initialize the texture using the intere model
242 	InitTexture(m);
243 
244 	gla->update();
245 	return true;
246 }
247 
EndEdit(MeshModel & m,GLArea *)248 void EditTexturePlugin::EndEdit(MeshModel &m , GLArea * )
249 {
250 	// Delete the widget
251 	for (unsigned i = 0; i < m.cm.face.size(); i++) m.cm.face[i].ClearS();
252 	if (widget != 0)
253 	{
254 		delete widget;
255 		delete dock;
256 		widget = 0;
257 		dock = 0;
258 	 }
259 }
260 
DrawXORRect(GLArea * gla)261 void EditTexturePlugin::DrawXORRect(GLArea *gla)
262 {
263     //	Draw the rectangle of the selection area
264     glMatrixMode(GL_PROJECTION);
265     glPushMatrix();
266     glLoadIdentity();
267     glOrtho(0, gla->width(), gla->height(),0,-1,1);
268     glMatrixMode(GL_MODELVIEW);
269     glPushMatrix();
270     glLoadIdentity();
271     glPushAttrib(GL_ENABLE_BIT);
272     glDisable(GL_DEPTH_TEST);
273     glDisable(GL_LIGHTING);
274     glDisable(GL_TEXTURE_2D);
275     glEnable(GL_COLOR_LOGIC_OP);
276     glLogicOp(GL_XOR);
277     glColor3f(1,1,1);
278 
279     glBegin(GL_LINE_LOOP);
280       glVertex2f(start.x(),start.y());
281       glVertex2f(cur.x(),start.y());
282       glVertex2f(cur.x(),cur.y());
283       glVertex2f(start.x(),cur.y());
284     glEnd();
285 
286     glDisable(GL_LOGIC_OP);
287     glPopAttrib();
288     glPopMatrix();
289     glMatrixMode(GL_PROJECTION);
290     glPopMatrix();
291     glMatrixMode(GL_MODELVIEW);
292 }
293 
InitTexture(MeshModel & m)294 void EditTexturePlugin::InitTexture(MeshModel &m)
295 {
296 	// Get the textures name and add the tab
297 	if (m.cm.textures.size() > 0)
298 	{
299 		for(unsigned i = 0; i < m.cm.textures.size(); i++)
300 			widget->AddRenderArea(m.cm.textures[i].c_str(), &m, i);
301 	}
302 	else widget->AddEmptyRenderArea();
303 }
304 
305 
306 // DA METTERE IN Clean.h
307 /**
308 Check if the parametrization is valid
309 */
HasCollapsedTextCoords(MeshModel & m)310 bool EditTexturePlugin::HasCollapsedTextCoords(MeshModel &m)
311 {
312 	if(!HasPerWedgeTexCoord(m.cm)) return true;
313 	for (CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
314 	{
315 		if(!(*fi).IsD())
316 		{
317 			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())
318 				return true;
319 		}
320 	}
321 	return false;
322 }
323