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 "renderarea.h"
25 #include "textureeditor.h"
26 #include <wrap/qt/trackball.h>
27 #include <math.h>
28 #include <stdlib.h>
29 
30 #define SELECTIONRECT 100
31 #define ORIGINRECT 200
32 #define MAX 100000
33 #define NOSEL -1
34 #define AREADIM 400
35 #define HRECT 6
36 
RenderArea(QWidget * parent,QString textureName,MeshModel * m,unsigned tnum)37 RenderArea::RenderArea(QWidget *parent, QString textureName, MeshModel *m, unsigned tnum) : QGLWidget(parent)
38 {
39     // Parameters
40     antialiased = true;
41     setBackgroundRole(QPalette::Base);
42     setAutoFillBackground(true);
43     textNum = tnum;
44     model = m;
45     image = QImage();
46     fileName = textureName;
47     if(textureName != QString())
48     {
49         if (QFile(textureName).exists())
50         {
51             image = QImage(textureName);
52             int bestW = pow(2.0,floor(::log(double(image.width()))/::log(2.0)));
53             int bestH = pow(2.0,floor(::log(double(image.height()))/::log(2.0)));
54             QImage imgGL = image.scaled(bestW,bestH,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
55             QImage tmpGL = QGLWidget::convertToGLFormat(imgGL);
56             glGenTextures(1, &id);
57             image = QImage(tmpGL).mirrored(false, true);
58         }
59         else textureName = QString();
60     }
61 
62     // Initialization
63     oldX = 0; oldY = 0;
64     viewport = vcg::Point2f(0,0);
65     tmpX = 0; tmpY = 0;
66     tb = new Trackball();
67     tb->center = Point3f(0, 0, 0);
68     tb->radius = 1;
69     panX = 0; panY = 0;
70     oldPX = 0; oldPY = 0;
71     posVX = 0; posVY = 0;
72     degenerate = false;
73 
74     brush = QBrush(Qt::green);
75     mode = View;
76     oldMode = NoMode;
77     editMode = Scale;
78     origin = QPointF();
79     start = QPoint();
80     end = QPoint();
81 
82     selectMode = Area;
83     selBit = CFaceO::NewBitFlag();
84     selVertBit = CVertexO::NewBitFlag();
85     selected = false;
86     selectedV = false;
87 
88     vertRect = QRect(0,0,RADIUS,RADIUS);
89     selRect = vector<QRect>();
90     for (int i = 0; i < 4; i++) selRect.push_back(QRect(0,0,RECTDIM,RECTDIM));
91     selStart = QPoint(0,0); selEnd = QPoint(0,0);
92     degree = 0.0f;
93     highlighted = NOSEL;
94     pressed = NOSEL;
95     posX = 0; posY = 0;
96     oScale = QPointF(0,0);
97     scaleX = 1; scaleY = 1;
98     orX = 0; orY = 0;
99     initVX = 0; initVY = 0;
100     locked = false;
101     drawnPath =	vector<Point2f>();
102     drawnPath1 = vector<Point2f>();
103     banList = vector<CFaceO*>();
104     drawP = false;
105     drawP1 = false;
106     path =	vector<CVertexO*>();
107     path1 =	vector<CVertexO*>();
108 
109     zoom = 1;
110 
111     rot = QImage(QString(":/images/rotate.png"));
112     scal = QImage(QString(":/images/scale.png"));
113 
114     this->setMouseTracking(true);
115     this->setCursor(Qt::PointingHandCursor);
116     this->setAttribute(Qt::WA_NoSystemBackground);
117     this->setAttribute(Qt::WA_KeyCompression, true);
118     this->setFocusPolicy(Qt::ClickFocus);
119 }
120 
~RenderArea()121 RenderArea::~RenderArea()
122 {
123     //CFaceO::DeleteBitFlag(selBit);
124     //CVertexO::DeleteBitFlag(selVertBit);
125 }
126 
127 // Change the Pen of the RenderArea
setPen(const QPen & pen)128 void RenderArea::setPen(const QPen &pen)
129 {
130     this->pen = pen;
131     update();
132 }
133 
134 // Chanhe the Brush of the RenderArea
setBrush(const QBrush & brush)135 void RenderArea::setBrush(const QBrush &brush)
136 {
137     this->brush = brush;
138     update();
139 }
140 
141 // Set the Antialiased property
setAntialiased(bool antialiased)142 void RenderArea::setAntialiased(bool antialiased)
143 {
144     this->antialiased = antialiased;
145     update();
146 }
147 
148 // Change the background texture
setTexture(QString path)149 void RenderArea::setTexture(QString path)
150 {
151     image = QImage(path);
152     fileName = path;
153     this->update();
154 }
155 
156 // Returns the name of the background image
GetTextureName()157 QString RenderArea::GetTextureName()
158 {
159     return fileName;
160 }
161 
162 // Inform the render area that the model has degenerate coordinates
SetDegenerate(bool deg)163 void RenderArea::SetDegenerate(bool deg)
164 {
165     degenerate = deg;
166 }
167 
paintEvent(QPaintEvent *)168 void RenderArea::paintEvent(QPaintEvent *)
169 {
170     // Init
171     QPainter painter(this);
172     painter.setPen(QPen(brush,2));
173     painter.setBrush(brush);
174     painter.setRenderHint(QPainter::Antialiasing, antialiased);
175     painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
176     tb->GetView();
177     tb->Apply();
178     maxX = 0; maxY = 0; minX = 0; minY = 0;
179 
180     if (model != NULL && HasPerWedgeTexCoord(model->cm) && image != QImage())
181     {
182         glEnable(GL_COLOR_LOGIC_OP);
183         glEnable(GL_DEPTH_TEST);
184         glLineWidth(1);
185         for (unsigned i = 0; i < model->cm.face.size(); i++)
186         {
187             glLogicOp(GL_XOR);
188             glColor3f(1,1,1);
189             // First draw the model in u,v space
190             if (model->cm.face[i].WT(0).n() == textNum)
191             {
192                 // While drawning, it counts the number of 'planes'
193                 if (model->cm.face[i].WT(0).u() > maxX || model->cm.face[i].WT(1).u() > maxX || model->cm.face[i].WT(2).u() > maxX)	maxX++;
194                 if (model->cm.face[i].WT(0).v() > maxY || model->cm.face[i].WT(1).v() > maxY || model->cm.face[i].WT(2).v() > maxY)	maxY++;
195                 if (model->cm.face[i].WT(0).u() < minX || model->cm.face[i].WT(1).u() < minX || model->cm.face[i].WT(2).u() < minX)	minX--;
196                 if (model->cm.face[i].WT(0).v() < minY || model->cm.face[i].WT(1).v() < minY || model->cm.face[i].WT(2).v() < minY)	minY--;
197 
198                 drawEdge(i); // Draw the edge of faces
199                 glDisable(GL_COLOR_LOGIC_OP);
200                 glColor3f(1.0f, 0.0f, 0.0f);
201                 //if (selected && model->cm.face[i].IsUserBit(selBit)) drawSelectedFaces(i); // Draw the selected faces
202                 if (selectedV && mode != UnifyVert)	drawSelectedVertexes(i); // Draw the selected vertex
203                 glEnable(GL_COLOR_LOGIC_OP);
204 
205             }
206         }
207         if (mode == UnifyVert) drawUnifyVertexes();
208 
209         glDisable(GL_LOGIC_OP);
210         glDisable(GL_COLOR_LOGIC_OP);
211         if (minX != 0 || minY != 0 || maxX != 0 || maxY != 0) drawBackground(); // Draw the background behind the model
212 
213         // 2D
214         glMatrixMode(GL_PROJECTION);
215         glPushMatrix();
216         glLoadIdentity();
217         glOrtho(0,this->width(),this->height(),0,-1,1);
218         glMatrixMode(GL_MODELVIEW);
219         glPushMatrix();
220         glLoadIdentity();
221         glPushAttrib(GL_ENABLE_BIT);
222         glDisable(GL_DEPTH_TEST);
223         glDisable(GL_LIGHTING);
224         glDisable(GL_TEXTURE_2D);
225         drawAxis(&painter); // and the axis, always in first plane
226         drawSelectionRectangle(&painter); // Draw the rectangle of selection
227         if (mode != UnifyVert) drawEditRectangle(&painter);
228         else drawUnifyRectangles(&painter); // Draw the rectangles for unify
229         glDisable(GL_LOGIC_OP);
230         glPopAttrib();
231         glPopMatrix();
232         glMatrixMode(GL_PROJECTION);
233         glPopMatrix();
234         glMatrixMode(GL_MODELVIEW);
235 
236         // Draw blend object
237         glDepthMask(GL_FALSE);
238         glLogicOp(GL_AND);
239         glEnable(GL_BLEND);
240         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
241         glColor4f(1.0f, 0.0f, 0.0f, 0.7f);
242         for (unsigned i = 0; i < model->cm.face.size(); i++)
243             if (selected && model->cm.face[i].IsUserBit(selBit)) drawSelectedFaces(i); // Draw the selected faces
244         glDepthMask(GL_TRUE);
245         glDisable(GL_BLEND);
246     }
247     else painter.drawText(this->visibleRegion().boundingRect().width()/2 - FMETRICX, this->visibleRegion().boundingRect().height()/2 - FMETRICY, tr("NO TEXTURE"));
248 
249     painter.setPen(palette().dark().color());
250     painter.setBrush(Qt::NoBrush);
251 }
252 
253 // Support methods for drawning
drawSelectedVertexes(int i)254 void RenderArea::drawSelectedVertexes(int i)
255 {
256     glDisable(GL_COLOR_LOGIC_OP);
257     glColor3f(1,0,0);
258     if (!isInside(&model->cm.face[i]))
259     {
260         for (int j = 0; j < 3; j++)
261         {
262             if(areaUV.contains(QPointF(model->cm.face[i].WT(j).u(), model->cm.face[i].WT(j).v())) && model->cm.face[i].V(j)->IsUserBit(selVertBit))
263                     DrawCircle(QPoint((origin.x() + (cos(degree) * (model->cm.face[i].WT(j).u() - origin.x()) - sin(degree) * (model->cm.face[i].WT(j).v() - origin.y()))) * AREADIM - posVX/zoom,
264                         (AREADIM - ((origin.y() + (sin(degree) * (model->cm.face[i].WT(j).u() - origin.x()) + cos(degree) * (model->cm.face[i].WT(j).v() - origin.y())))) * AREADIM) - posVY/zoom));
265         }
266     }
267     glColor3f(0,0,0);
268     glEnable(GL_COLOR_LOGIC_OP);
269 }
270 
drawSelectedFaces(int i)271 void RenderArea::drawSelectedFaces(int i)
272 {
273     glBegin(GL_TRIANGLES);
274     for (int j = 0; j < 3; j++)
275     {
276         if (editMode == Scale)
277             glVertex3f((oScale.x() + (model->cm.face[i].WT(j).u() - oScale.x()) * scaleX) * AREADIM - panX/zoom,
278                 AREADIM - ((oScale.y() + (model->cm.face[i].WT(j).v() - oScale.y()) * scaleY) * AREADIM) - panY/zoom, 1);
279         else glVertex3f((origin.x() + (cos(degree) * (model->cm.face[i].WT(j).u() - origin.x()) - sin(degree) * (model->cm.face[i].WT(j).v() - origin.y()))) * AREADIM - panX/zoom,
280                 AREADIM - ((origin.y() + (sin(degree) * (model->cm.face[i].WT(j).u() - origin.x()) + cos(degree) * (model->cm.face[i].WT(j).v() - origin.y()))) * AREADIM) - panY/zoom, 1);
281     }
282     glEnd();
283 }
284 
drawEdge(int i)285 void RenderArea::drawEdge(int i)
286 {
287     glBegin(GL_LINE_LOOP);
288     for (int j = 0; j < 3; j++)
289     {
290         if (mode != EditVert)
291         {
292             if (!model->cm.face[i].IsUserBit(selBit))
293                 glVertex3f(model->cm.face[i].WT(j).u() * AREADIM , AREADIM - (model->cm.face[i].WT(j).v() * AREADIM), 1);
294             else if (editMode == Scale) glVertex3f((oScale.x() + (model->cm.face[i].WT(j).u() - oScale.x()) * scaleX) * AREADIM - panX/zoom,
295                         AREADIM - ((oScale.y() + (model->cm.face[i].WT(j).v() - oScale.y()) * scaleY) * AREADIM) - panY/zoom, 1);
296                  else glVertex3f((origin.x() + (cos(degree) * (model->cm.face[i].WT(j).u() - origin.x()) - sin(degree) * (model->cm.face[i].WT(j).v() - origin.y()))) * AREADIM - panX/zoom,
297                         AREADIM - ((origin.y() + (sin(degree) * (model->cm.face[i].WT(j).u() - origin.x()) + cos(degree) * (model->cm.face[i].WT(j).v() - origin.y()))) * AREADIM) - panY/zoom, 1);
298         }
299         else
300         {
301             if (areaUV.contains(QPointF(model->cm.face[i].WT(j).u(), model->cm.face[i].WT(j).v())) && model->cm.face[i].V(j)->IsUserBit(selVertBit) && !isInside(&model->cm.face[i]))
302                 glVertex3f((origin.x() + (cos(degree) * (model->cm.face[i].WT(j).u() - origin.x()) - sin(degree) * (model->cm.face[i].WT(j).v() - origin.y()))) * AREADIM - posVX/zoom,
303                         AREADIM - ((origin.y() + (sin(degree) * (model->cm.face[i].WT(j).u() - origin.x()) + cos(degree) * (model->cm.face[i].WT(j).v() - origin.y()))) * AREADIM) - posVY/zoom, 1);
304             else glVertex3f(model->cm.face[i].WT(j).u() * AREADIM , AREADIM - (model->cm.face[i].WT(j).v() * AREADIM), 1);
305         }
306     }
307     glEnd();
308 }
309 
drawUnifyVertexes()310 void RenderArea::drawUnifyVertexes()
311 {
312     glDisable(GL_COLOR_LOGIC_OP);
313     glColor3f(1,0,0);
314     if (uvertA != QPoint()) DrawCircle(QPoint((origin.x() + (cos(degree) * (tua - origin.x()) - sin(degree) * (tva - origin.y()))) * AREADIM - posVX/zoom,
315                                 AREADIM - ((origin.y() + (sin(degree) * (tua - origin.x()) + cos(degree) * (tva - origin.y()))) * AREADIM) - posVY/zoom));
316     if (uvertB != QPoint()) DrawCircle(QPoint((origin.x() + (cos(degree) * (tub - origin.x()) - sin(degree) * (tvb - origin.y()))) * AREADIM - posVX/zoom,
317                                 AREADIM - ((origin.y() + (sin(degree) * (tub - origin.x()) + cos(degree) * (tvb - origin.y()))) * AREADIM) - posVY/zoom));
318     if (uvertA1 != QPoint()) DrawCircle(QPoint((origin.x() + (cos(degree) * (tua1 - origin.x()) - sin(degree) * (tva1 - origin.y()))) * AREADIM - posVX/zoom,
319                                 AREADIM - ((origin.y() + (sin(degree) * (tua1 - origin.x()) + cos(degree) * (tva1 - origin.y()))) * AREADIM) - posVY/zoom));
320     if (uvertB1 != QPoint()) DrawCircle(QPoint((origin.x() + (cos(degree) * (tub1 - origin.x()) - sin(degree) * (tvb1 - origin.y()))) * AREADIM - posVX/zoom,
321                                 AREADIM - ((origin.y() + (sin(degree) * (tub1 - origin.x()) + cos(degree) * (tvb1 - origin.y()))) * AREADIM) - posVY/zoom));
322     glColor3f(0,0,0);
323     glEnable(GL_COLOR_LOGIC_OP);
324 }
325 
drawBackground()326 void RenderArea::drawBackground()
327 {
328     glColor3f(1,1,1);
329     glBindTexture(GL_TEXTURE_2D, id);
330     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
331     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
332     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image.width(), image.height(), GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
333     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
334     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
335     glEnable(GL_TEXTURE_2D);
336     for (int x = minX; x < maxX; x++)
337     {
338         for (int y = minY; y < maxY; y++)
339         {
340             glBegin(GL_QUADS);
341                 glTexCoord2f(0.0,0.0);
342                 glVertex3f(0.0 + x*AREADIM,0.0 - y*AREADIM,0.0);
343                 glTexCoord2f(1.0,0.0);
344                 glVertex3f(1.0*AREADIM + x*AREADIM,0.0 - y*AREADIM,0.0);
345                 glTexCoord2f(1.0,1.0);
346                 glVertex3f(1.0*AREADIM + x*AREADIM,1.0*AREADIM - y*AREADIM,0.0);
347                 glTexCoord2f(0.0,1.0);
348                 glVertex3f(0.0 + x*AREADIM,1.0*AREADIM - y*AREADIM,0.0);
349             glEnd();
350         }
351     }
352     glDisable(GL_TEXTURE_2D);
353 }
354 
drawAxis(QPainter * painter)355 void RenderArea::drawAxis(QPainter* painter)
356 {
357     // Line and text (native Qt)
358     int w = this->visibleRegion().boundingRect().width();
359     int h = this->visibleRegion().boundingRect().height();
360     painter->drawLine(0,h,w,h);
361     painter->drawLine(0,h,0,0);
362     // Calculate the coords and draw it
363     float ox = (float)-viewport.X()*zoom/(AREADIM*zoom), oy = (float)(AREADIM*zoom - h + viewport.Y()*zoom)/(AREADIM*zoom);
364     /*O:*/painter->drawText(TRANSLATE, h - TRANSLATE, QString("(%1,%2)").arg(ox).arg(oy));
365     /*Y:*/painter->drawText(TRANSLATE, TRANSLATE*3, QString("(%1,%2)").arg(ox).arg((float)(AREADIM*zoom + viewport.Y()*zoom)/(AREADIM*zoom)));
366     /*X:*/painter->drawText(w - TRANSLATE*18, h - TRANSLATE, QString("(%1,%2)").arg((float)(w-viewport.X()*zoom)/(AREADIM*zoom)).arg(oy));
367     painter->drawText(TRANSLATE, TRANSLATE*6, QString("V"));
368     painter->drawText(w - TRANSLATE*23, h - TRANSLATE, QString("U"));
369 }
370 
drawSelectionRectangle(QPainter * painter)371 void RenderArea::drawSelectionRectangle(QPainter *painter)
372 {
373     if (start != QPoint() && end != QPoint())
374     {
375         painter->setPen(QPen(QBrush(Qt::gray),1));
376         painter->setBrush(QBrush(Qt::NoBrush));
377         painter->drawRect(area);
378     }
379 }
380 
drawEditRectangle(QPainter * painter)381 void RenderArea::drawEditRectangle(QPainter *painter)
382 {
383     if (selection != QRect() && (mode == Edit || mode == EditVert))
384     {
385         // The rectangle of editing
386         painter->setPen(QPen(QBrush(Qt::yellow),2));
387         painter->setBrush(QBrush(Qt::NoBrush));
388         if (mode == Edit) painter->drawRect(QRect(selection.x() - posX, selection.y() - posY, selection.width(), selection.height()));
389         else painter->drawRect(QRect(selection.x() - posVX, selection.y() - posVY, selection.width(), selection.height()));
390         if (mode == Edit || (mode == EditVert && VCount > 1))
391         {
392             // Rectangle on the corner
393             painter->setPen(QPen(QBrush(Qt::black),1));
394             for (unsigned l = 0; l < selRect.size(); l++)
395             {
396                 if (l == highlighted) painter->setBrush(QBrush(Qt::yellow));
397                 else painter->setBrush(QBrush(Qt::NoBrush));
398                 painter->drawRect(selRect[l]);
399                 if (editMode == Scale && mode == Edit) painter->drawImage(selRect[l],scal,QRect(0,0,scal.width(),scal.height()));
400                 else painter->drawImage(selRect[l],rot,QRect(0,0,rot.width(),rot.height()));
401             }
402             // and the origin of the rotation
403             if ((editMode == Rotate && mode == Edit) || mode == EditVert)
404             {
405                 painter->setPen(QPen(QBrush(Qt::black),1));
406                 if (highlighted == ORIGINRECT) painter->setBrush(QBrush(Qt::blue));
407                 else painter->setBrush(QBrush(Qt::yellow));
408                 if (mode == Edit) painter->drawEllipse(QRect(originR.x() - posX - orX, originR.y() - posY - orY, RADIUS, RADIUS));
409                 else painter->drawEllipse(QRect(originR.x() - posVX - orX, originR.y() - posVY - orY, RADIUS, RADIUS));
410             }
411         }
412     }
413 }
414 
drawUnifyRectangles(QPainter * painter)415 void RenderArea::drawUnifyRectangles(QPainter *painter)
416 {
417     if (unifyRA != QRect())
418     {
419         painter->setPen(QPen(QBrush(Qt::blue),1));
420         painter->setBrush(QBrush(Qt::NoBrush));
421         painter->drawRect(unifyRA);
422         painter->drawText(unifyRA.center().x() - RADIUS*2, unifyRA.center().y(), tr("A"));
423     }
424     if (unifyRB != QRect())
425     {
426         painter->drawRect(unifyRB);
427         painter->drawText(unifyRB.center().x() - RADIUS*2, unifyRB.center().y(), tr("B"));
428     }
429     if (unifyRA != QRect() && unifyRB != QRect()) painter->drawLine(unifyRA.center(), unifyRB.center());
430     if (unifyRA1 != QRect())
431     {
432         painter->drawRect(unifyRA1);
433         painter->drawText(unifyRA1.center().x() - RADIUS*2, unifyRA1.center().y(), tr("A'"));
434     }
435     if (unifyRB1 != QRect())
436     {
437         painter->drawRect(unifyRB1);
438         painter->drawText(unifyRB1.center().x() - RADIUS*2, unifyRB1.center().y(), tr("B'"));
439     }
440     if (unifyRA1 != QRect() && unifyRB1 != QRect())	painter->drawLine(unifyRA1.center(), unifyRB1.center());
441     if (drawP)
442     {
443         painter->setPen(QPen(QBrush(Qt::red),2));
444         for (unsigned k = 0; k < drawnPath.size()-1; k++)
445             painter->drawLine(ToScreenSpace(drawnPath[k].X(), drawnPath[k].Y()), ToScreenSpace(drawnPath[k+1].X(),drawnPath[k+1].Y()));
446     }
447     if (drawP1)
448     {
449         for (unsigned k = 0; k < drawnPath1.size()-1; k++)
450             painter->drawLine(ToScreenSpace(drawnPath1[k].X(), drawnPath1[k].Y()), ToScreenSpace(drawnPath1[k+1].X(),drawnPath1[k+1].Y()));
451     }
452 }
453 // Mouse Event:
mousePressEvent(QMouseEvent * e)454 void RenderArea::mousePressEvent(QMouseEvent *e)
455 {
456     if((e->buttons() & Qt::LeftButton))
457     {
458         if ((mode == Edit || mode == EditVert) && highlighted == NOSEL)
459         {
460             this->ChangeMode(SPECIALMODE);
461             pressed = NOSEL;
462             selected = false;
463             selectedV = false;
464             selVertBit = CVertexO::NewBitFlag();
465             for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearUserBit(selBit);
466         }
467         switch(mode)
468         {
469             case View:
470                 handlePressView(e);
471                 break;
472             case Edit:
473                 handlePressEdit(e);
474                 break;
475             case EditVert:
476                 handlePressEdit(e);
477                 break;
478             case Select:
479                 handlePressSelect(e);
480                 break;
481             case UnifyVert:
482                 handlePressSelect(e);
483                 break;
484         }
485     }
486     else if((e->buttons() & Qt::MidButton))
487     {
488         // Pan
489         oldMode = mode;
490         this->ChangeMode(VIEWMODE);
491         oldX = e->x(); oldY = e->y();
492         tmpX = viewport.X(); tmpY = viewport.Y();
493         tb->MouseDown(e->x(), AREADIM-e->y(), QT2VCG(e->button(), e->modifiers()));
494         this->update();
495     }
496 }
497 
handlePressView(QMouseEvent * e)498 void RenderArea::handlePressView(QMouseEvent *e)
499 {
500     oldX = e->x(); oldY = e->y();
501     tmpX = viewport.X(); tmpY = viewport.Y();
502     tb->MouseDown(e->x(), AREADIM-e->y(), QT2VCG(e->button(), e->modifiers()));
503     this->update();
504 }
505 
handlePressSelect(QMouseEvent * e)506 void RenderArea::handlePressSelect(QMouseEvent *e)
507 {
508     start = e->pos();
509     end = e->pos();
510 }
511 
handlePressEdit(QMouseEvent * e)512 void RenderArea::handlePressEdit(QMouseEvent *e)
513 {
514     tpanX = e->x();
515     tpanY = e->y();
516     pressed = highlighted;
517     if (highlighted > NOSEL && highlighted < selRect.size())
518     {
519         rectX = selRect[highlighted].center().x();
520         rectY = selRect[highlighted].center().y();
521         if (mode == Edit)
522         {
523             oldSRX = selection.width();
524             oldSRY = selection.height();
525             scaleX = 1; scaleY = 1;
526         }
527         int perno;
528         if (highlighted == 0) perno = 3;
529         else if (highlighted == 1) perno = 2;
530         else if (highlighted == 2) perno = 1;
531         else perno = 0;
532         oScale = ToUVSpace(selRect[perno].center().x(), selRect[perno].center().y());
533         B2 = (float)(rectX - originR.center().x())*(rectX - originR.center().x()) + (rectY - originR.center().y())*(rectY - originR.center().y());
534         Rm = (float)(rectY - originR.center().y()) / (rectX - originR.center().x());
535         Rq = (float) rectY - Rm * rectX;
536     }
537 }
538 
mouseReleaseEvent(QMouseEvent * e)539 void RenderArea::mouseReleaseEvent(QMouseEvent *e)
540 {
541     switch(mode)
542     {
543         case View:
544             handleReleaseView(e);
545             break;
546         case Edit:
547             handleReleaseEdit(e);
548             break;
549         case EditVert:
550             handleReleaseEdit(e);
551             break;
552         case Select:
553             handleReleaseSelect(e);
554             break;
555         case UnifyVert:
556             area = QRect();
557             locked = false;
558             if (unifyRB1 != QRect()) UnifySet();
559             this->update();
560             break;
561     }
562 }
563 
handleReleaseView(QMouseEvent * e)564 void RenderArea::handleReleaseView(QMouseEvent *e)
565 {
566     if (selection != QRect())
567     {
568         UpdateSelectionArea((viewport.X() - initVX)*zoom, (viewport.Y() - initVY)*zoom);
569         originR.moveCenter(QPoint(originR.x() + (viewport.X() - initVX)*zoom, originR.y() + (viewport.Y() - initVY)*zoom));
570         origin = ToUVSpace(originR.center().x(), originR.center().y());
571     }
572     initVX = viewport.X(); initVY = viewport.Y();
573     if (oldMode != NoMode)
574     {
575         this->ChangeMode(oldMode);
576         oldMode = NoMode;
577     }
578 }
579 
handleReleaseEdit(QMouseEvent * e)580 void RenderArea::handleReleaseEdit(QMouseEvent *e)
581 {
582     oldPX = panX;
583     oldPY = panY;
584     if (pressed == ORIGINRECT)	// Drag origin -> Update the position of the rectangle of rotation and the real point in UV
585     {
586         originR = QRect(originR.x() - posX - orX, originR.y() - posY - orY, RADIUS, RADIUS);
587         origin = ToUVSpace(originR.center().x(), originR.center().y());
588         orX = 0; orY = 0;
589     }
590     else if (pressed == SELECTIONRECT)
591     {
592         if (mode == Edit && posX != 0)	// Drag selection -> Update the position of the selection area and the rotatation rect
593         {
594             selection = QRect(selection.x() - posX, selection.y() - posY, selection.width(), selection.height());
595             originR.moveCenter(QPoint(originR.center().x() - posX, originR.center().y() - posY));
596             origin = ToUVSpace(originR.center().x(), originR.center().y());
597             posX = 0; posY = 0;
598             if (selected) UpdateUV();
599         }
600         else if (mode == EditVert && posVX != 0)
601         {
602             selection = QRect(selection.x() - posVX, selection.y() - posVY, selection.width(), selection.height());
603             originR.moveCenter(QPoint(originR.center().x() - posVX, originR.center().y() - posVY));
604             origin = ToUVSpace(originR.center().x(), originR.center().y());
605             if (selectedV) UpdateVertex();
606         }
607     }
608     else if (pressed > NOSEL && pressed < selRect.size())
609     {
610         if (editMode == Rotate && mode == Edit)
611         {
612             RotateComponent(degree);
613             RecalculateSelectionArea();
614             degree = 0;
615         }
616         else if (scaleX != 1 && scaleY != 1 && mode == Edit)
617         {
618             ScaleComponent(scaleX, scaleY);
619             RecalculateSelectionArea();
620             scaleX = 1;
621             scaleY = 1;
622             oScale = QPointF(0,0);
623         }
624         else if (mode == EditVert)
625         {
626             selStart = QPoint(MAX,MAX);
627             selEnd = QPoint(-MAX,-MAX);
628             RotateComponent(degree);
629             selection = QRect(QPoint(selStart.x() - VRADIUS, selStart.y() - VRADIUS), QPoint(selEnd.x() + VRADIUS, selEnd.y() + VRADIUS));
630             QPointF a = ToUVSpace(selection.x(), selection.y());
631             QPointF b = ToUVSpace(selection.bottomRight().x(),selection.bottomRight().y());
632             areaUV = QRectF(a, QSizeF(b.x()-a.x(), b.y()-a.y()));
633             UpdateSelectionAreaV(0,0);
634             degree = 0;
635         }
636     }
637 }
638 
handleReleaseSelect(QMouseEvent * e)639 void RenderArea::handleReleaseSelect(QMouseEvent *e)
640 {
641     start = QPoint();
642     end = QPoint();
643     area = QRect();
644     switch (selectMode)
645     {
646         case Area:
647             if (selected)
648             {
649                 selection = QRect(selStart, selEnd);
650                 UpdateSelectionArea(0,0);
651                 origin = ToUVSpace(selection.center().x(), selection.center().y());
652                 originR = QRect(selection.center().x()-RADIUS/2, selection.center().y()-RADIUS/2, RADIUS, RADIUS);
653                 this->ChangeMode(EDITFACEMODE);
654                 this->ShowFaces();
655             }
656             break;
657         case Connected:
658             SelectConnectedComponent(e->pos());
659             if (selected)
660             {
661                 selection = QRect(selStart, selEnd);
662                 UpdateSelectionArea(0,0);
663                 RecalculateSelectionArea();
664                 origin = ToUVSpace(selection.center().x(), selection.center().y());
665                 originR = QRect(selection.center().x()-RADIUS/2, selection.center().y()-RADIUS/2, RADIUS, RADIUS);
666                 this->ChangeMode(EDITFACEMODE);
667                 this->ShowFaces();
668             }
669             break;
670         case Vertex:
671             if (selectedV)
672             {
673                 CountVertexes();
674                 selection = QRect(QPoint(selStart.x() - RADIUS/2, selStart.y() - RADIUS/2), QPoint(selEnd.x() + RADIUS/2, selEnd.y() + RADIUS/2));
675                 if (VCount > 1)
676                 {
677                     UpdateSelectionAreaV(0,0);
678                     origin = ToUVSpace(selection.center().x(), selection.center().y());
679                     originR = QRect(selection.center().x()-RADIUS/2, selection.center().y()-RADIUS/2, RADIUS, RADIUS);
680                 }
681                 this->ChangeMode(EDITVERTEXMODE);
682             }
683             break;
684     }
685     this->update();
686 }
687 
mouseMoveEvent(QMouseEvent * e)688 void RenderArea::mouseMoveEvent(QMouseEvent *e)
689 {
690     int sx = (e->x() - oldX)/zoom, sy = (e->y() - oldY)/zoom;
691     if((e->buttons() & Qt::LeftButton) && image != QImage())
692     {
693         if (mode == View)
694         {
695             tb->Translate(Point3f(- oldX + e->x(), - oldY + e->y(), zoom));
696             viewport = Point2f(tmpX + sx, tmpY + sy);
697             this->update();
698         }
699         else if (mode == Edit || mode == EditVert)	handleMoveEdit(e);
700         else if (mode == Select || mode == UnifyVert) handleMoveSelect(e);
701     }
702     else if((e->buttons() & Qt::MidButton) && image != QImage()) // Pan
703     {
704         tb->Translate(Point3f(- oldX + e->x(), - oldY + e->y(), zoom));
705         viewport = Point2f(tmpX + sx, tmpY + sy);
706         this->update();
707     }
708     else if (image != QImage())// No click
709     {
710         if (mode == Edit || mode == EditVert)
711         {
712             for (unsigned y = 0; y < selRect.size(); y++)
713             {
714                 if (selRect[y].contains(e->pos()) && (mode == Edit || (mode == EditVert && VCount > 1)))
715                 {
716                     if (highlighted != y) this->update(selRect[y]);
717                     highlighted = y;
718                     return;
719                 }
720             }
721             if (originR.contains(e->pos()) && ((mode == Edit && editMode == Rotate) || mode == EditVert))
722             {
723                 if (highlighted != ORIGINRECT) this->update(originR);
724                 highlighted = ORIGINRECT;
725                 return;
726             }
727             if (selection.contains(e->pos()))
728             {
729                 if (highlighted == ORIGINRECT) this->update(originR);
730                 else if (highlighted < selRect.size()) this->update(selRect[highlighted]);
731                 highlighted = SELECTIONRECT;
732                 return;
733             }
734             if (highlighted != NOSEL)
735             {
736                 if (highlighted == ORIGINRECT) this->update(originR);
737                 else if (highlighted < selRect.size()) this->update(selRect[highlighted]);
738             }
739             highlighted = NOSEL;
740         }
741     }
742 }
743 
handleMoveEdit(QMouseEvent * e)744 void RenderArea::handleMoveEdit(QMouseEvent *e)
745 {
746     int tX = tpanX - e->x();
747     int tY = tpanY - e->y();
748     if (pressed == SELECTIONRECT)
749     {
750         // Move the selection ara
751         if (mode == Edit)
752         {
753             panX = oldPX + tpanX - e->x();
754             panY = oldPY + tpanY - e->y();
755         }
756         if (tX != 0 || tY != 0)
757         {
758             QPoint ta = QPoint(selection.topLeft().x() - tX, selection.topLeft().y() - tY);
759             QPoint tb = QPoint(selection.topRight().x() - tX, selection.topRight().y() - tY);
760             QPoint tc = QPoint(selection.bottomLeft().x() - tX, selection.bottomLeft().y() - tY);
761             QPoint td = QPoint(selection.bottomRight().x() - tX, selection.bottomRight().y() - tY);
762             if (mode == Edit)
763             {
764                 posX = tX; posY = tY;
765                 selRect[0].moveCenter(ta); selRect[1].moveCenter(tb);
766                 selRect[2].moveCenter(tc); selRect[3].moveCenter(td);
767             }
768             else
769             {
770                 posVX = tX; posVY = tY;
771                 selRect[0].moveBottomRight(ta); selRect[1].moveBottomLeft(tb);
772                 selRect[2].moveTopRight(tc); selRect[3].moveTopLeft(td);
773             }
774         }
775     }
776     else if (pressed == ORIGINRECT)
777     {
778         orX = tX;
779         orY = tY;
780         this->update(originR);
781     }
782     else if (pressed > NOSEL && pressed < selRect.size())
783     {
784         if (editMode == Scale && mode == Edit) HandleScale(e->pos());
785         else HandleRotate(e->pos());
786     }
787     this->update();
788 }
789 
handleMoveSelect(QMouseEvent * e)790 void RenderArea::handleMoveSelect(QMouseEvent *e)
791 {
792     if ((mode == Select && selectMode != Connected) || mode == UnifyVert)
793     {
794         end = e->pos();
795         int x1, x2, y1, y2;
796         if (start.x() < end.x()) {x1 = start.x(); x2 = end.x();} else {x1 = end.x(); x2 = start.x();}
797         if (start.y() < end.y()) {y1 = start.y(); y2 = end.y();} else {y1 = end.y(); y2 = start.y();}
798         area = QRect(x1,y1,x2-x1,y2-y1);
799         if (mode == Select)
800         {
801             if (selectMode == Area) SelectFaces();
802             else SelectVertexes();
803         }
804         else if (!locked) SelectVertexes();
805         this->update();
806     }
807 }
808 
mouseDoubleClickEvent(QMouseEvent * e)809 void RenderArea::mouseDoubleClickEvent(QMouseEvent *e)
810 {
811     switch(mode)
812     {
813         case View:	// Center the screen on the mouse click position
814             viewport = Point2f(viewport.X() - e->x()/zoom + (this->visibleRegion().boundingRect().width()/zoom)/2,
815                 viewport.Y() - e->y()/zoom + (this->visibleRegion().boundingRect().height()/zoom)/2);
816             oldX = 0; oldY = 0;
817             tb->track.SetTranslate(Point3f(viewport.X(), viewport.Y(), 1));
818             tb->Scale(zoom);
819             this->update();
820             break;
821         case Edit:	// Change edit mode
822             if (selection.contains(e->pos()))
823             {
824                 if (editMode == Rotate) editMode = Scale;
825                 else editMode = Rotate;
826                 this->update();
827             }
828             break;
829     }
830 }
831 
wheelEvent(QWheelEvent * e)832 void RenderArea::wheelEvent(QWheelEvent*e)
833 {
834     if (image != QImage())
835     {
836         // Handle the zoom for any mode
837         int cwx = viewport.X() - (this->visibleRegion().boundingRect().width()/zoom)/2;
838         int cwy = viewport.Y() - (this->visibleRegion().boundingRect().height()/zoom)/2;
839         if (e->delta() > 0) zoom /= 0.75;
840         else zoom *= 0.75;
841         // Change the viewport, putting the center of the screen on the mouseposition
842         cwx += (this->visibleRegion().boundingRect().width()/zoom)/2;
843         cwy += (this->visibleRegion().boundingRect().height()/zoom)/2;
844         viewport = Point2f(cwx, cwy);
845         ResetTrack(false);
846         tb->Scale(zoom);
847         if (selectedV)
848         {
849             if (mode == UnifyVert) UpdateUnify();
850             else UpdateVertexSelection();
851         }
852         else if (selected) RecalculateSelectionArea();
853         originR.moveCenter(ToScreenSpace(origin.x(), origin.y()));
854         initVX = viewport.X(); initVY = viewport.Y();
855         this->update();
856     }
857 }
858 
keyPressEvent(QKeyEvent * e)859 void RenderArea::keyPressEvent(QKeyEvent *e)
860 {
861     if (e->key() == Qt::Key_H) ResetPosition();
862     else e->ignore();
863 }
864 
865 // Remap the uv coord out of border using clamp method
RemapClamp()866 void RenderArea::RemapClamp()
867 {
868     for (unsigned i = 0; i < model->cm.face.size(); i++)
869     {
870         if (model->cm.face[i].WT(0).n() == textNum && !model->cm.face[i].IsD())
871         {
872             model->cm.face[i].ClearUserBit(selBit);
873             for (unsigned j = 0; j < 3; j++)
874             {
875                 if (model->cm.face[i].WT(j).u() > 1) model->cm.face[i].WT(j).u() = 1;
876                 else if (model->cm.face[i].WT(j).u() < 0) model->cm.face[i].WT(j).u() = 0;
877                 if (model->cm.face[i].WT(j).v() > 1) model->cm.face[i].WT(j).v() = 1;
878                 else if (model->cm.face[i].WT(j).v() < 0) model->cm.face[i].WT(j).v() = 0;
879             }
880         }
881     }
882     panX = 0; panY = 0; tpanX = 0; tpanY = 0; oldPX = 0; oldPY = 0;
883     ResetTrack(true);
884     vcg::tri::UpdateTopology<CMeshO>::FaceFaceFromTexCoord(model->cm);
885     selection = QRect();
886     this->update();
887     emit UpdateModel();
888 }
889 
890 // Remap the uv coord out of border using mod function
RemapMod()891 void RenderArea::RemapMod()
892 {
893     for (unsigned i = 0; i < model->cm.face.size(); i++)
894     {
895         if (model->cm.face[i].WT(0).n() == textNum && !model->cm.face[i].IsD())
896         {
897             model->cm.face[i].ClearUserBit(selBit);
898             for (unsigned j = 0; j < 3; j++)
899             {
900                 float u = model->cm.face[i].WT(j).u();
901                 float v = model->cm.face[i].WT(j).v();
902                 if (u < 0) u = u + (int)u + 1;
903                 else if (u > 1) u = u - (int)u;
904                 if (v < 0) v = v + (int)v + 1;
905                 else if (v > 1) v = v - (int)v;
906                 model->cm.face[i].WT(j).u() = u;
907                 model->cm.face[i].WT(j).v() = v;
908             }
909         }
910     }
911     panX = 0; panY = 0; tpanX = 0; tpanY = 0; oldPX = 0; oldPY = 0;
912     ResetTrack(true);
913     vcg::tri::UpdateTopology<CMeshO>::FaceFaceFromTexCoord(model->cm);
914     selection = QRect();
915     this->update();
916     emit UpdateModel();
917 }
918 
919 // Change the tool's action mode
ChangeMode(int modenumber)920 void RenderArea::ChangeMode(int modenumber)
921 {
922     if (mode == UnifyVert && modenumber != UNIFYMODE)
923     {
924         resetUnifyData();
925         drawnPath.clear(); drawnPath1.clear();
926         drawP = false; drawP1 = false;
927     }
928     switch(modenumber)
929     {
930         case VIEWMODE:
931             if (mode != View)
932             {
933                 mode = View;
934                 this->setCursor(Qt::PointingHandCursor);
935             }
936             break;
937         case EDITFACEMODE:
938             if (mode != Edit)
939             {
940                 mode = Edit;
941                 highlighted = SELECTIONRECT;
942                 this->setCursor(Qt::SizeAllCursor);
943             }
944             break;
945         case SELECTMODE:
946             if (mode != Select)
947             {
948                 if (selection != QRect())
949                 {
950                     if (selectMode == Vertex)
951                     {
952                         mode = EditVert; selectedV = true;
953                         UpdateSelectionAreaV(0,0);
954                         for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearUserBit(selBit);
955                     }
956                     else
957                     {
958                         mode = Edit; selected = true;
959                         for (unsigned i = 0; i < model->cm.vert.size(); i++) model->cm.vert[i].ClearUserBit(selVertBit);
960                     }
961                     this->setCursor(Qt::SizeAllCursor);
962                 }
963                 else
964                 {
965                     mode = Select;
966                     for (unsigned i = 0; i < model->cm.face.size(); i++)
967                     {
968                         model->cm.face[i].ClearUserBit(selBit);	model->cm.face[i].ClearS();
969                     }
970                     for (unsigned i = 0; i < model->cm.vert.size(); i++) model->cm.vert[i].ClearUserBit(selVertBit);
971                     emit UpdateModel();
972                     this->setCursor(Qt::CrossCursor);
973                 }
974             }
975             break;
976         case SPECIALMODE:	// For internal use... reset the selection
977             mode = Select;
978             for (unsigned i = 0; i < model->cm.face.size(); i++)
979             {
980                 model->cm.face[i].ClearUserBit(selBit);	model->cm.face[i].ClearS();
981             }
982             selection = QRect();
983             this->setCursor(Qt::CrossCursor);
984             emit UpdateModel();
985             break;
986         case EDITVERTEXMODE:
987             if (mode != EditVert)
988             {
989                 if (selection != QRect())
990                 {
991                     mode = EditVert; selectedV = true;
992                     this->setCursor(Qt::SizeAllCursor);
993                 }
994                 else
995                 {
996                     mode = Select;
997                     this->setCursor(Qt::CrossCursor);
998                 }
999             }
1000             break;
1001         case UNIFYMODE:
1002             if (mode != UnifyVert)
1003             {
1004                 mode = UnifyVert;
1005                 resetUnifyData();
1006                 if (selected) {for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearS();}
1007                 selection = QRect(); selected = false; selectedV = false;
1008                 for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearUserBit(selBit);
1009                 selVertBit = CVertexO::NewBitFlag();
1010                 this->setCursor(Qt::CrossCursor);
1011                 model->updateDataMask(MeshModel::MM_VERTFACETOPO | MeshModel::MM_FACEFACETOPO);
1012                 //model->cm.face.EnableVFAdjacency();
1013                 //model->cm.vert.EnableVFAdjacency();
1014                 //model->cm.face.EnableFFAdjacency();
1015                 UpdateUnifyTopology();
1016             }
1017             break;
1018     }
1019     this->update();
1020 }
1021 
resetUnifyData()1022 void RenderArea::resetUnifyData()
1023 {
1024     unifyRA = QRect();
1025     unifyRA1 = QRect();
1026     unifyRB = QRect();
1027     unifyRB1 = QRect();
1028     uvertA = QPoint();
1029     uvertA1 = QPoint();
1030     uvertB = QPoint();
1031     uvertB1 = QPoint();
1032 }
1033 
1034 // Change the selection function
ChangeSelectMode(int selectindex)1035 void RenderArea::ChangeSelectMode(int selectindex)
1036 {
1037     switch(selectindex)
1038     {
1039         case SELECTAREA:
1040             if (selectMode != Area && selectMode != Connected) selection = QRect();
1041             selectMode = Area;
1042             break;
1043         case SELECTCONNECTED:
1044             if (selectMode != Connected && selectMode != Area) selection = QRect();
1045             selectMode = Connected;
1046             break;
1047         case SELECTVERTEX:
1048             if (selectMode != Vertex) selection = QRect();
1049             selectMode = Vertex;
1050             break;
1051         default:
1052             selectMode = Area;
1053             break;
1054     }
1055     if (selectedV && selectMode != Vertex)
1056     {
1057         areaUV = QRectF();
1058         selVertBit = CVertexO::NewBitFlag();
1059         selectedV = false;
1060     }
1061     if (selected && selectMode == Vertex)
1062     {
1063         selected = false;
1064         //selBit = CFaceO::NewBitFlag();
1065         for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearUserBit(selBit);
1066         for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearS();
1067         emit UpdateModel();
1068     }
1069 }
1070 
RotateComponent(float theta)1071 void RenderArea::RotateComponent(float theta)
1072 {
1073     // Calcolate the new position of the vertex of the selected component after a rotation.
1074     // The rotation is done around the selected point
1075     if (origin != QPoint())
1076     {
1077         float sinv = sin(theta);
1078         float cosv = cos(theta);
1079         if (selected)
1080         {
1081             for (unsigned i = 0; i < model->cm.face.size(); i++)
1082             {
1083                 if (model->cm.face[i].WT(0).n() == textNum && !model->cm.face[i].IsD() && (!selected || (selected && model->cm.face[i].IsUserBit(selBit))))
1084                 for (unsigned j = 0; j < 3; j++)
1085                 {
1086                     float u = origin.x() + (cosv * (model->cm.face[i].WT(j).u() - origin.x()) - sinv * (model->cm.face[i].WT(j).v() - origin.y()));
1087                     float v = origin.y() + (sinv * (model->cm.face[i].WT(j).u() - origin.x()) + cosv * (model->cm.face[i].WT(j).v() - origin.y()));
1088                     model->cm.face[i].WT(j).u() = u;
1089                     model->cm.face[i].WT(j).v() = v;
1090                 }
1091             }
1092         }
1093         else if (selectedV)
1094         {
1095             for (unsigned i = 0; i < model->cm.face.size(); i++)
1096             {
1097                 for (unsigned j = 0; j < 3; j++)
1098                 {
1099                     if (areaUV.contains(QPointF(model->cm.face[i].WT(j).u(),model->cm.face[i].WT(j).v()))
1100                         && model->cm.face[i].V(j)->IsUserBit(selVertBit) && !model->cm.face[i].V(j)->IsD())
1101                     {
1102                         float u = origin.x() + (cosv * (model->cm.face[i].WT(j).u() - origin.x()) - sinv * (model->cm.face[i].WT(j).v() - origin.y()));
1103                         float v = origin.y() + (sinv * (model->cm.face[i].WT(j).u() - origin.x()) + cosv * (model->cm.face[i].WT(j).v() - origin.y()));
1104                         model->cm.face[i].WT(j).u() = u;
1105                         model->cm.face[i].WT(j).v() = v;
1106                         QPoint tmp = ToScreenSpace(u, v);
1107                         UpdateBoundingArea(tmp,tmp);
1108                     }
1109                 }
1110             }
1111         }
1112         this->update();
1113         emit UpdateModel();
1114     }
1115 }
1116 
ScaleComponent(float percX,float percY)1117 void RenderArea::ScaleComponent(float percX, float percY)
1118 {
1119     // Scale the selected component. The origin is set to the clicked point
1120     for (unsigned i = 0; i < model->cm.face.size(); i++)
1121     {
1122         if (model->cm.face[i].WT(0).n() == textNum && selected && model->cm.face[i].IsUserBit(selBit) && !model->cm.face[i].IsD())
1123         for (unsigned j = 0; j < 3; j++)
1124         {
1125             float x = oScale.x() + (model->cm.face[i].WT(j).u() - oScale.x()) * percX;
1126             float y = oScale.y() + (model->cm.face[i].WT(j).v() - oScale.y()) * percY;
1127             model->cm.face[i].WT(j).u() = x;
1128             model->cm.face[i].WT(j).v() = y;
1129         }
1130     }
1131     this->update();
1132     emit UpdateModel();
1133 }
1134 
UpdateUV()1135 void RenderArea::UpdateUV()
1136 {
1137     // After a move of component, re-calculate the new UV coordinates
1138     for (unsigned i = 0; i < model->cm.face.size(); i++)
1139     {
1140         if (model->cm.face[i].WT(0).n() == textNum && model->cm.face[i].IsUserBit(selBit) && !model->cm.face[i].IsD())
1141         {
1142             for (unsigned j = 0; j < 3; j++)
1143             {
1144                 model->cm.face[i].WT(j).u() = model->cm.face[i].WT(j).u() - (float)panX/(AREADIM*zoom);
1145                 model->cm.face[i].WT(j).v() = model->cm.face[i].WT(j).v() + (float)panY/(AREADIM*zoom);
1146             }
1147         }
1148     }
1149     panX = 0; panY = 0; tpanX = 0; tpanY = 0; oldPX = 0; oldPY = 0;
1150     this->update();
1151     emit UpdateModel();
1152 }
1153 
UpdateVertex()1154 void RenderArea::UpdateVertex()
1155 {
1156     // After a move of vertex, re-calculate the new UV coordinates
1157     for (unsigned i = 0; i < model->cm.face.size(); i++)
1158     {
1159         if (!isInside(&model->cm.face[i]))
1160         {
1161             for (unsigned j = 0; j < 3; j++)
1162             {
1163                 if (areaUV.contains(QPointF(model->cm.face[i].WT(j).u(),model->cm.face[i].WT(j).v()))
1164                     && model->cm.face[i].V(j)->IsUserBit(selVertBit) && !model->cm.face[i].V(j)->IsD())
1165                 {
1166                     model->cm.face[i].WT(j).u() = model->cm.face[i].WT(j).u() - (float)posVX/(AREADIM*zoom);
1167                     model->cm.face[i].WT(j).v() = model->cm.face[i].WT(j).v() + (float)posVY/(AREADIM*zoom);
1168                 }
1169             }
1170         }
1171     }
1172     areaUV.moveCenter(QPointF(areaUV.center().x() - (float)posVX/(AREADIM*zoom), areaUV.center().y() + (float)posVY/(AREADIM*zoom)));
1173     tpanX = 0; tpanY = 0; posVX = 0; posVY = 0;
1174     this->update();
1175     emit UpdateModel();
1176 }
1177 
ResetTrack(bool resetViewPort)1178 void RenderArea::ResetTrack(bool resetViewPort)
1179 {
1180     // Reset the viewport of the trackball
1181     tb->center = Point3f(0, 0, 0);
1182     tb->track.SetScale(1);
1183     if (resetViewPort) viewport = Point2f(0,0);
1184     oldX = 0; oldY = 0;
1185     tb->track.SetTranslate(Point3f(viewport.X(), viewport.Y(), 1));
1186 }
1187 
SelectFaces()1188 void RenderArea::SelectFaces()
1189 {
1190     // Check if a face is inside the rectangle of selection and mark it
1191     selStart = QPoint(MAX,MAX);
1192     selEnd = QPoint(-MAX,-MAX);
1193     selected = false;
1194     selection = QRect();
1195     CMeshO::FaceIterator fi;
1196     for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi)
1197     {
1198         if ((*fi).WT(0).n() == textNum && !(*fi).IsD())
1199         {
1200             (*fi).ClearUserBit(selBit);
1201             QVector<QPoint> t = QVector<QPoint>();
1202             t.push_back(ToScreenSpace((*fi).WT(0).u(), (*fi).WT(0).v()));
1203             t.push_back(ToScreenSpace((*fi).WT(1).u(), (*fi).WT(1).v()));
1204             t.push_back(ToScreenSpace((*fi).WT(2).u(), (*fi).WT(2).v()));
1205             QRegion r = QRegion(QPolygon(t));
1206             if (r.intersects(area))
1207             {
1208                 (*fi).SetUserBit(selBit);
1209                 UpdateBoundingArea(r.boundingRect().topLeft(), r.boundingRect().bottomRight());
1210                 if (!selected) selected = true;
1211             }
1212         }
1213     }
1214 }
1215 
SelectVertexes()1216 void RenderArea::SelectVertexes()
1217 {
1218     // Check if a vertex is inside the rectangle of selection
1219     selStart = QPoint(MAX,MAX);
1220     selEnd = QPoint(-MAX,-MAX);
1221     selectedV = false;
1222     selection = QRect();
1223     QPointF a = ToUVSpace(area.x(), area.y());
1224     QPointF b = ToUVSpace(area.bottomRight().x(),area.bottomRight().y());
1225     areaUV = QRectF(a, QSizeF(b.x()-a.x(), b.y()-a.y()));
1226     CMeshO::FaceIterator fi;
1227     for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi)
1228     {
1229         if ((*fi).WT(0).n() == textNum && !(*fi).IsD())
1230         {
1231             for (int j = 0; j < 3; j++)
1232             {
1233                 QPoint tmp = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v());
1234                 if (area.contains(tmp))
1235                 {
1236                     (*fi).V(j)->SetUserBit(selVertBit);
1237                     UpdateBoundingArea(tmp, tmp);
1238                     if (!selectedV) selectedV = true;
1239                     if (mode == UnifyVert && !locked)
1240                     {
1241                         locked = true;
1242                         handleUnifySelection(fi, j);
1243                         return;
1244                     }
1245                 }
1246             }
1247         }
1248     }
1249     if (mode != UnifyVert) CheckVertex();
1250 }
1251 
CheckVertex()1252 void RenderArea::CheckVertex()
1253 {
1254     // Search for unselected vertices in UV Space
1255     banList.clear();
1256     CMeshO::FaceIterator fi;
1257     for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi)
1258     {
1259         if ((*fi).WT(0).n() == textNum && !(*fi).IsD())
1260         {
1261             bool go = false;
1262             for (int j = 0; j < 3; j++)
1263             {
1264                 if ((*fi).V(j)->IsUserBit(selVertBit))
1265                 {
1266                     if (!areaUV.contains(QPointF((*fi).WT(j).u(), (*fi).WT(j).v()))) go = true;
1267                     else {go = false; break;}
1268                 }
1269             }
1270             if (go) banList.push_back(&(*fi));
1271         }
1272     }
1273 }
1274 
handleUnifySelection(CMeshO::FaceIterator fi,int j)1275 void RenderArea::handleUnifySelection(CMeshO::FaceIterator fi, int j)
1276 {
1277     if (unifyRA == QRect())
1278     {
1279         unifyRA = QRect(QPoint(selStart.x() - VRADIUS, selStart.y() - VRADIUS), QPoint(selEnd.x() + VRADIUS, selEnd.y() + VRADIUS));
1280         unifyA = (*fi).V(j);
1281         firstface = &(*fi);
1282         uvertA = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v());
1283         tua = (*fi).WT(j).u(); tva = (*fi).WT(j).v();
1284         drawnPath.clear();
1285         drawnPath.push_back(Point2f(tua,tva));
1286     }
1287     else if (unifyRB == QRect())
1288     {
1289         unifyRB = QRect(QPoint(selStart.x() - VRADIUS, selStart.y() - VRADIUS), QPoint(selEnd.x() + VRADIUS, selEnd.y() + VRADIUS));
1290         unifyB = (*fi).V(j);
1291         uvertB = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v());
1292         tub = (*fi).WT(j).u(); tvb = (*fi).WT(j).v();
1293         path.clear();
1294         if (unifyA->IsB() && unifyB->IsB())
1295         {
1296             path = FindPath(unifyA, unifyB, firstface, 0);
1297             drawP = true;
1298         }
1299         this->update();
1300     }
1301     else if (unifyRA1 == QRect())
1302     {
1303         firstface1 = &(*fi);
1304         unifyRA1 = QRect(QPoint(selStart.x() - VRADIUS, selStart.y() - VRADIUS), QPoint(selEnd.x() + VRADIUS, selEnd.y() + VRADIUS));
1305         unifyA1 = (*fi).V(j);
1306         uvertA1 = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v());
1307         tua1 = (*fi).WT(j).u(); tva1 = (*fi).WT(j).v();
1308         drawnPath1.clear();
1309         drawnPath1.push_back(Point2f(tua1,tva1));
1310     }
1311     else if (unifyRB1 == QRect())
1312     {
1313         unifyRB1 = QRect(QPoint(selStart.x() - VRADIUS, selStart.y() - VRADIUS), QPoint(selEnd.x() + VRADIUS, selEnd.y() + VRADIUS));
1314         unifyB1 = (*fi).V(j);
1315         uvertB1 = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v());
1316         tub1 = (*fi).WT(j).u(); tvb1 = (*fi).WT(j).v();
1317         path1.clear();
1318         if (unifyA1->IsB() && unifyB1->IsB())
1319         {
1320             path1 = FindPath(unifyA1, unifyB1, firstface1, 1);
1321             drawP1 = true;
1322         }
1323         this->update();
1324     }
1325 }
1326 
SelectConnectedComponent(QPoint e)1327 void RenderArea::SelectConnectedComponent(QPoint e)
1328 {
1329     // Select a series of faces with the same UV coord on the edge
1330     selStart = QPoint(MAX,MAX);
1331     selEnd = QPoint(-MAX,-MAX);
1332     selected = false;
1333     //selBit = CFaceO::NewBitFlag();
1334     for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearUserBit(selBit);
1335     unsigned index = 0;
1336     vector<CFaceO*> Q = vector<CFaceO*>();
1337 
1338     // Search the clicked face
1339     for(unsigned i = 0; i < model->cm.face.size(); i++)
1340     {
1341         if (model->cm.face[i].WT(0).n() == textNum)
1342         {
1343             QVector<QPoint> t = QVector<QPoint>();
1344             t.push_back(ToScreenSpace(model->cm.face[i].WT(0).u(), model->cm.face[i].WT(0).v()));
1345             t.push_back(ToScreenSpace(model->cm.face[i].WT(1).u(), model->cm.face[i].WT(1).v()));
1346             t.push_back(ToScreenSpace(model->cm.face[i].WT(2).u(), model->cm.face[i].WT(2).v()));
1347             QRegion r = QRegion(QPolygon(t));
1348             if (r.contains(e))
1349             {
1350                 Q.push_back(&model->cm.face[i]);
1351                 model->cm.face[i].SetUserBit(selBit);
1352                 UpdateBoundingArea(r.boundingRect().topLeft(), r.boundingRect().bottomRight());
1353                 selected = true;
1354                 break;
1355             }
1356         }
1357     }
1358     // Select all the adjacentfaces
1359     while (index < Q.size())
1360     {
1361         for (int j = 0; j < 3; j++)
1362         {
1363             CFaceO* p = Q[index]->FFp(j);
1364             if (p != 0 && !p->IsUserBit(selBit))
1365             {
1366                 p->SetUserBit(selBit);
1367                 Q.push_back(p);
1368                 QPoint tmp = ToScreenSpace(p->WT(j).u(), p->WT(j).v());
1369                 UpdateBoundingArea(tmp, tmp);
1370             }
1371         }
1372         index++;
1373     }
1374 }
1375 
1376 // Clear every selected faces or vertices
ClearSelection()1377 void RenderArea::ClearSelection()
1378 {
1379     //selBit = CFaceO::NewBitFlag();
1380     for (unsigned i = 0; i < model->cm.face.size(); i++)
1381     {
1382         model->cm.face[i].ClearUserBit(selBit);
1383         model->cm.face[i].ClearS();
1384     }
1385     selVertBit = CVertexO::NewBitFlag();
1386     selection = QRect();
1387     this->update();
1388     emit UpdateModel();
1389 }
1390 
1391 // Invert selected faces
InvertSelection()1392 void RenderArea::InvertSelection()
1393 {
1394     if (selected)
1395     {
1396         for (unsigned i = 0; i < model->cm.face.size(); i++)
1397         {
1398             if (model->cm.face[i].WT(0).n() == textNum)
1399             {
1400                 if (model->cm.face[i].IsUserBit(selBit)) model->cm.face[i].ClearUserBit(selBit);
1401                 else model->cm.face[i].SetUserBit(selBit);
1402             }
1403         }
1404         RecalculateSelectionArea();
1405         originR.moveCenter(selection.center());
1406         origin = ToUVSpace(originR.center().x(), originR.center().y());
1407         this->update();
1408         ShowFaces();
1409     }
1410     else if (selectedV)
1411     {
1412         for (unsigned i = 0; i < model->cm.vert.size(); i++)
1413         {
1414             if (model->cm.vert[i].IsUserBit(selVertBit)) model->cm.vert[i].ClearUserBit(selVertBit);
1415             else model->cm.vert[i].SetUserBit(selVertBit);
1416         }
1417         UpdateVertexSelection();
1418         this->update();
1419     }
1420 }
1421 
1422 // Flip the selected faces (mode = true -> horizontal, mode = false -> vertical)
Flip(bool mode)1423 void RenderArea::Flip(bool mode)
1424 {
1425     if (selected)
1426     {
1427         QPointF mid = ToUVSpace(selection.center().x(), selection.center().y());
1428         for (unsigned i = 0; i < model->cm.face.size(); i++)
1429         {
1430             if (model->cm.face[i].WT(0).n() == textNum)
1431             {
1432                 if (model->cm.face[i].IsUserBit(selBit))
1433                 {
1434                     for (int j = 0; j < 3; j++)
1435                     {
1436                         if (mode) model->cm.face[i].WT(j).u() = 2.0f * mid.x() - model->cm.face[i].WT(j).u();
1437                         else model->cm.face[i].WT(j).v() = 2.0f * mid.y() - model->cm.face[i].WT(j).v();
1438                     }
1439                 }
1440             }
1441         }
1442         RecalculateSelectionArea();
1443         this->update();
1444     }
1445 }
1446 
1447 // Collapse a couple of vertices
UnifyCouple()1448 void RenderArea::UnifyCouple()
1449 {
1450     // Calculate the average coordinates and unify a couple of vertices
1451     if (VCount == 2)
1452     {
1453         float tu = (vc1.u() + vc2.u())/2.0;
1454         float tv = (vc1.v() + vc2.v())/2.0;
1455 
1456         for (unsigned i = 0; i < model->cm.face.size(); i++)
1457         {
1458             for (unsigned j = 0; j < 3; j++)
1459             {
1460                 if (!isInside(&model->cm.face[i]) && (model->cm.face[i].V(j) == collapse1 || model->cm.face[i].V(j) == collapse2))
1461                 {
1462                     model->cm.face[i].WT(j).u() = tu;
1463                     model->cm.face[i].WT(j).v() = tv;
1464                 }
1465             }
1466         }
1467         selectedV = false;
1468         selVertBit = CVertexO::NewBitFlag();
1469         areaUV = QRectF();
1470         selection = QRect();
1471         this->ChangeMode(SELECTMODE);
1472         this->update();
1473         emit UpdateModel();
1474     }
1475 }
1476 
1477 // Unify a set of border vertices among the selected path
UnifySet()1478 void RenderArea::UnifySet()
1479 {
1480     // Unify a set of vertices
1481     if (path.size() == path1.size() && drawP && drawP1)
1482     {
1483         for (unsigned i = 0; i < path.size(); i++)
1484         {
1485             float mu = (drawnPath[i].X() + drawnPath1[i].X())/2.0;
1486             float mv = (drawnPath[i].Y() + drawnPath1[i].Y())/2.0;
1487             int n = path[i]->VFi();
1488             CFaceO *next = path[i]->VFp();
1489             while (n != -1)
1490             {
1491                 if (drawnPath[i].X() == next->WT(n).u() && drawnPath[i].Y() == next->WT(n).v())
1492                 {
1493                     next->WT(n).u() = mu;
1494                     next->WT(n).v() = mv;
1495                 }
1496                 CFaceO* previous = next;
1497                 next = next->VFp(n);
1498                 n = previous->VFi(n);
1499                 if (next == 0) break;
1500             }
1501             int n1 = path1[i]->VFi();
1502             CFaceO *next1 = path1[i]->VFp();
1503             while (n1 != -1)
1504             {
1505                 if (drawnPath1[i].X() == next1->WT(n1).u() && drawnPath1[i].Y() == next1->WT(n1).v())
1506                 {
1507                     next1->WT(n1).u() = mu;
1508                     next1->WT(n1).v() = mv;
1509                 }
1510                 CFaceO* previus1 = next1;
1511                 next1 = next1->VFp(n1);
1512                 n1 = previus1->VFi(n1);
1513                 if (next1 == 0) break;
1514             }
1515         }
1516         UpdateUnifyTopology();
1517     }
1518     selectedV = false;
1519     for (unsigned i = 0; i < model->cm.vert.size(); i++) model->cm.vert[i].ClearUserBit(selVertBit);
1520     areaUV = QRectF();
1521     selection = QRect();
1522     unifyA = 0; unifyB = 0; unifyA1 = 0; unifyB1 = 0;
1523     firstface = 0; firstface1 = 0;
1524     drawP = false; drawP1 = false;
1525     uvertA = QPoint(); uvertA1 = QPoint(); uvertB = QPoint(); uvertB1 = QPoint();
1526     unifyRA = QRect(); unifyRA1 = QRect(); unifyRB = QRect(); unifyRB1 = QRect();
1527     this->update();
1528     emit UpdateModel();
1529 }
1530 
FindPath(CVertexO * begin,CVertexO * end,CFaceO * first,int pathN)1531 vector<CVertexO*> RenderArea::FindPath(CVertexO* begin, CVertexO* end, CFaceO* first, int pathN)
1532 {
1533     // Find a path from the selected vertex, walking from LEFT TO RIGHT only on border edge...
1534     vector<CVertexO*> path = vector<CVertexO*>();
1535     unsigned index = 0;
1536     vector<CFaceO*> Q = vector<CFaceO*>();
1537     Q.push_back(first);
1538     path.push_back(begin);
1539     first->SetV();
1540     bool finish = false;
1541     int notcontrol = -1;
1542     int lastadd = 0, lastex = -1;
1543     /* Add all the adjacent faces to the vertex.
1544        For each face in Stack Q
1545          if the edge is a border one and contains the last added vertex and is on the right
1546             enqueue all adjacent faces to the other vertex
1547             add the other vertex to the path
1548     */
1549     float tu, tv;
1550     if (pathN == 0) {tu = tua; tv = tva;}
1551     else {tu = tua1; tv = tva1;}
1552     CFaceO* nextb, *previusb;
1553     int nb = begin->VFi();
1554     nextb = begin->VFp(), previusb = first;
1555     while (nb != -1)
1556     {
1557         if (tu == nextb->WT(nb).u() && tv == nextb->WT(nb).v() && nextb != first) Q.push_back(nextb);
1558         previusb = nextb;
1559         nextb = nextb->VFp(nb);
1560         nb = previusb->VFi(nb);
1561         if (nextb == 0) break;
1562     }
1563     bool verso;
1564     if (pathN == 0)
1565     {
1566         if (tua < tub) verso = true;
1567         else verso = false;
1568     }
1569     else
1570     {
1571         if (tua1 < tub1) verso = true;
1572         else verso = false;
1573     }
1574 
1575     if (begin->IsB() && end->IsB())
1576     while (index < Q.size())
1577     {
1578         bool excluded = false;
1579         int oldsize = Q.size();
1580         CFaceO* p = Q[index];
1581         float oldu;
1582         if (pathN == 0) oldu = tua;
1583         else oldu = tua1;
1584         if (!p->IsV() || (p->IsV() && index == 0))
1585         {
1586             for (int j = 0; j < 3; j++)
1587             {
1588                 if (p->IsB(j) && j != notcontrol)
1589                 {
1590                     notcontrol = j;
1591                     CVertexO *tmp1 = p->V(j);
1592                     CVertexO *tmp2 = p->V((j+1)%3);
1593                     bool added = false;
1594                     int n, oldn;
1595                     CFaceO *next, *previous;
1596                     float tu, tv;
1597                     if (tmp1 == path[path.size()-1] && ((verso && p->WT(j).u() >= oldu) || (!verso && p->WT(j).u() <= oldu)))
1598                     {
1599                         oldu = p->WT(j).u();
1600                         path.push_back(tmp2);
1601                         if (pathN == 0) drawnPath.push_back(Point2f(p->WT((j+1)%3).u(),p->WT((j+1)%3).v()));
1602                         else drawnPath1.push_back(Point2f(p->WT((j+1)%3).u(),p->WT((j+1)%3).v()));
1603                         if (tmp2 == end) {finish = true; break;}
1604                         n = tmp2->VFi(), oldn = (j+1)%3;
1605                         next = tmp2->VFp(), previous = p;
1606                         added = true;
1607                         lastadd = index; lastex = j;
1608                     }
1609                     else if (tmp2 == path[path.size()-1] && ((verso && p->WT(j).u() >= oldu) || (!verso && p->WT(j).u() <= oldu)))
1610                     {
1611                         oldu = p->WT(j).u();
1612                         path.push_back(tmp1);
1613                         if (pathN == 0) drawnPath.push_back(Point2f(p->WT(j).u(),p->WT(j).v()));
1614                         else drawnPath1.push_back(Point2f(p->WT(j).u(),p->WT(j).v()));
1615                         if (tmp1 == end) {finish = true; break;}
1616                         n = tmp1->VFi(), oldn = j;
1617                         next = tmp1->VFp(), previous = p;
1618                         added = true;
1619                         lastadd = index; lastex = j;
1620                     }
1621                     if (added)
1622                     {
1623                         index = Q.size()-1;
1624                         tu = p->WT(oldn).u(); tv = p->WT(oldn).v();
1625                         while (n != -1)
1626                         {
1627                             if (tu == next->WT(n).u() && tv == next->WT(n).v() && next != p && !next->IsV())
1628                                 Q.push_back(next);
1629                             previous = next;
1630                             oldn = n;
1631                             next = next->VFp(n);
1632                             n = previous->VFi(n);
1633                             if (next == 0) break;
1634                         }
1635                         break;
1636                     }
1637                     else excluded = true;
1638                 }
1639             }
1640             p->SetV();
1641             if (!p->IsB(0) && !p->IsB(1) && !p->IsB(2) && index != 0) excluded = true;
1642         }
1643         if (finish) break;
1644         // casi degeneri...
1645         if (oldsize == Q.size() && !excluded)
1646         {
1647             if (index == Q.size()-1) {index = lastadd; p->ClearV();}	// Force to search again the same face...
1648         }
1649         else notcontrol = -1;
1650         index++;
1651         if (index == Q.size() && end != path[path.size()-1])
1652         {
1653             index = lastadd;
1654             notcontrol = lastex;
1655             Q[index]->ClearV();
1656         }
1657     }
1658 
1659     for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearV();
1660     return path;
1661 }
1662 
HandleScale(QPoint e)1663 void RenderArea::HandleScale(QPoint e)
1664 {
1665     // Move the rectangle of scaling and resize the selection area
1666     int tx = rectX - tpanX + e.x();
1667     int ty = rectY - tpanY + e.y();
1668     switch(highlighted)
1669     {
1670         case 0:	// Top Left
1671             if (tx > selection.x() + selection.width() - RECTDIM) tx = selection.x() + selection.width() - RECTDIM;
1672             if (ty > selection.y() + selection.height() - RECTDIM) ty = selection.y() + selection.height() - RECTDIM;
1673             selRect[0].moveCenter(QPoint(tx, ty));
1674             selRect[2] = QRect(tx - RECTDIM/2, selRect[2].y(), RECTDIM, RECTDIM);
1675             selRect[1] = QRect(selRect[1].x(), ty - RECTDIM/2, RECTDIM, RECTDIM);
1676             selection.setTopLeft(selRect[0].center());
1677             selection.setBottomLeft(selRect[2].center());
1678             selection.setTopRight(selRect[1].center());
1679             this->update(selRect[1]);
1680             break;
1681         case 1: // Top Right
1682             if (tx < selection.x() + RECTDIM) tx = selection.x() +  RECTDIM;
1683             if (ty > selection.y() + selection.height() - RECTDIM) ty = selection.y() + selection.height() - RECTDIM;
1684             selRect[1].moveCenter(QPoint(tx, ty));
1685             selRect[3] = QRect(tx - RECTDIM/2, selRect[3].y(), RECTDIM, RECTDIM);
1686             selRect[0] = QRect(selRect[0].x(), ty - RECTDIM/2, RECTDIM, RECTDIM);
1687             selection.setTopRight(selRect[1].center());
1688             selection.setTopLeft(selRect[0].center());
1689             selection.setBottomRight(selRect[3].center());
1690             this->update(selRect[0]);
1691             break;
1692         case 2:	// Bottom Left
1693             if (tx > selection.x() + selection.width() - RECTDIM) tx = selection.x() + selection.width() - RECTDIM;
1694             if (ty < selection.y() + RECTDIM) ty = selection.y() + RECTDIM;
1695             selRect[2].moveCenter(QPoint(tx, ty));
1696             selRect[0] = QRect(tx - RECTDIM/2, selRect[0].y(), RECTDIM, RECTDIM);
1697             selRect[3] = QRect(selRect[3].x(), ty - RECTDIM/2, RECTDIM, RECTDIM);
1698             selection.setTopLeft(selRect[0].center());
1699             selection.setBottomLeft(selRect[2].center());
1700             selection.setBottomRight(selRect[3].center());
1701             this->update(selRect[3]);
1702             break;
1703         case 3:	// Bottom Right
1704             if (tx < selection.x() + RECTDIM) tx = selection.x() + RECTDIM;
1705             if (ty < selection.y() + RECTDIM) ty = selection.y() + RECTDIM;
1706             selRect[3].moveCenter(QPoint(tx, ty));
1707             selRect[1] = QRect(tx - RECTDIM/2, selRect[1].y(), RECTDIM, RECTDIM);
1708             selRect[2] = QRect(selRect[2].x(), ty - RECTDIM/2, RECTDIM, RECTDIM);
1709             selection.setTopRight(selRect[1].center());
1710             selection.setBottomLeft(selRect[2].center());
1711             selection.setBottomRight(selRect[3].center());
1712             this->update(selRect[2]);
1713             break;
1714     }
1715     this->update(selRect[highlighted]);
1716     this->update(selRect[(highlighted+2)%selRect.size()]);
1717     originR.moveCenter(selection.center());
1718     origin = ToUVSpace(originR.center().x(), originR.center().y());
1719     // calculate scaling
1720     scaleX = (float)selection.width() / oldSRX;
1721     scaleY = (float)selection.height() / oldSRY;
1722 
1723     this->update(selection);
1724 }
1725 
HandleRotate(QPoint e)1726 void RenderArea::HandleRotate(QPoint e)
1727 {
1728     // Calculate the angle of rotazion
1729     float A2 = (e.x() - originR.center().x())*(e.x() - originR.center().x()) + (e.y() - originR.center().y())*(e.y() - originR.center().y());
1730     float C2 = (rectX - e.x())*(rectX - e.x()) + (rectY - e.y()) * (rectY -e.y());
1731     degree = acos((C2 - A2 - B2) / (-2*sqrt(A2)*sqrt(B2)));
1732     float ny = (float) Rm * e.x() + Rq;
1733     switch(highlighted)
1734     {
1735     case 0:
1736         if (ny > e.y()) degree = -degree;
1737         break;
1738     case 1:
1739         if (ny < e.y())
1740             degree = -degree;
1741         break;
1742     case 2:
1743         if (ny > e.y()) degree = -degree;
1744         break;
1745     case 3:
1746         if (ny < e.y()) degree = -degree;
1747         break;
1748     }
1749     this->update();
1750 }
1751 
1752 // Find the new size of the selection rectangle after an edit
RecalculateSelectionArea()1753 void RenderArea::RecalculateSelectionArea()
1754 {
1755     selStart = QPoint(MAX,MAX);
1756     selEnd = QPoint(-MAX,-MAX);
1757     CMeshO::FaceIterator fi;
1758     for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi)
1759     {
1760         if ((*fi).IsUserBit(selBit) && !(*fi).IsD())
1761         {
1762             QPoint a = ToScreenSpace((*fi).WT(0).u(), (*fi).WT(0).v());
1763             QPoint b = ToScreenSpace((*fi).WT(1).u(), (*fi).WT(1).v());
1764             QPoint c = ToScreenSpace((*fi).WT(2).u(), (*fi).WT(2).v());
1765             // >> There's a BUG IN QREGION: I can't create a region if points are too near!!!! <<
1766             SetUpRegion(a, b, c);
1767         }
1768     }
1769     if (selected && selStart.x() < selEnd.x() && selStart.y() < selEnd.y())
1770     {
1771         selection = QRect(selStart, selEnd);
1772         UpdateSelectionArea(0,0);
1773     }
1774 }
1775 
SetUpRegion(QPoint a,QPoint b,QPoint c)1776 void RenderArea::SetUpRegion(QPoint a, QPoint b, QPoint c)
1777 {
1778     // Avoid a bug in Qt by calculating the region manually
1779     if (a.x() < selStart.x()) selStart.setX(a.x());
1780     if (b.x() < selStart.x()) selStart.setX(b.x());
1781     if (c.x() < selStart.x()) selStart.setX(c.x());
1782     if (a.y() < selStart.y()) selStart.setY(a.y());
1783     if (b.y() < selStart.y()) selStart.setY(b.y());
1784     if (c.y() < selStart.y()) selStart.setY(c.y());
1785     if (a.x() > selEnd.x()) selEnd.setX(a.x());
1786     if (b.x() > selEnd.x()) selEnd.setX(b.x());
1787     if (c.x() > selEnd.x()) selEnd.setX(c.x());
1788     if (a.y() > selEnd.y()) selEnd.setY(a.y());
1789     if (b.y() > selEnd.y()) selEnd.setY(b.y());
1790     if (c.y() > selEnd.y()) selEnd.setY(c.y());
1791 }
1792 
UpdateSelectionArea(int x,int y)1793 void RenderArea::UpdateSelectionArea(int x, int y)
1794 {
1795     // Update the buttons of the selection area
1796     selection.moveCenter(QPoint(selection.center().x() + x, selection.center().y() + y));
1797     selRect[0].moveCenter(selection.topLeft());
1798     selRect[1].moveCenter(selection.topRight());
1799     selRect[2].moveCenter(selection.bottomLeft());
1800     selRect[3].moveCenter(selection.bottomRight());
1801 }
1802 
UpdateSelectionAreaV(int x,int y)1803 void RenderArea::UpdateSelectionAreaV(int x, int y)
1804 {
1805     // Update the buttons of the selection area for vertices
1806     selection.moveCenter(QPoint(selection.center().x() + x, selection.center().y() + y));
1807     selRect[0].moveBottomRight(selection.topLeft());
1808     selRect[1].moveBottomLeft(selection.topRight());
1809     selRect[2].moveTopRight(selection.bottomLeft());
1810     selRect[3].moveTopLeft(selection.bottomRight());
1811 }
1812 
UpdateVertexSelection()1813 void RenderArea::UpdateVertexSelection()
1814 {
1815     // Recalculate the rectangle for selection of vertices
1816     selStart = QPoint(MAX,MAX);
1817     selEnd = QPoint(-MAX,-MAX);
1818     selectedV = false;
1819     selection = QRect();
1820     CMeshO::FaceIterator fi;
1821     for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi)
1822     {
1823         if ((*fi).WT(0).n() == textNum && !(*fi).IsD())
1824         {
1825             for (int j = 0; j < 3; j++)
1826             {
1827                 QPoint tmp = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v());
1828                 if ((*fi).V(j)->IsUserBit(selVertBit) && areaUV.contains(QPointF((*fi).WT(j).u(), (*fi).WT(j).v())))
1829                 {
1830                     UpdateBoundingArea(tmp,tmp);
1831                     if (!selectedV) selectedV = true;
1832                 }
1833             }
1834         }
1835     }
1836     selection = QRect(QPoint(selStart.x() - VRADIUS, selStart.y() - VRADIUS), QPoint(selEnd.x() + VRADIUS, selEnd.y() + VRADIUS));
1837     QPointF a = ToUVSpace(selection.x(), selection.y());
1838     QPointF b = ToUVSpace(selection.bottomRight().x(),selection.bottomRight().y());
1839     areaUV = QRectF(a, QSizeF(b.x()-a.x(), b.y()-a.y()));
1840     UpdateSelectionAreaV(0,0);
1841 }
1842 
UpdateUnify()1843 void RenderArea::UpdateUnify()
1844 {
1845     // Update the Unify infrastructure after a zoom
1846     if (unifyRA != QRect())
1847     {
1848         unifyRA.moveCenter(ToScreenSpace(tua, tva));
1849         uvertA = unifyRA.topLeft();
1850     }
1851     if (unifyRA1 != QRect())
1852     {
1853         unifyRA1.moveCenter(ToScreenSpace(tua1, tva1));
1854         uvertA1 = unifyRA1.center();
1855     }
1856     if (unifyRB != QRect())
1857     {
1858         unifyRB.moveCenter(ToScreenSpace(tub, tvb));
1859         uvertB = unifyRB.center();
1860     }
1861     if (unifyRB1 != QRect())
1862     {
1863         unifyRB1.moveCenter(ToScreenSpace(tub1, tvb1));
1864         uvertB1 = unifyRB1.center();
1865     }
1866 }
1867 
ToUVSpace(int x,int y)1868 QPointF RenderArea::ToUVSpace(int x, int y)
1869 {
1870     // Convert a point from screen-space to uv-space
1871     return QPointF((float)(x - viewport.X()*zoom)/(AREADIM*zoom), (float)(AREADIM*zoom - y + viewport.Y()*zoom)/(AREADIM*zoom));
1872 }
1873 
ToScreenSpace(float u,float v)1874 QPoint RenderArea::ToScreenSpace(float u, float v)
1875 {
1876     // Convert a point from uv-space to screen space
1877     return QPoint(u * AREADIM*zoom + viewport.X()*zoom, AREADIM*zoom - (v * AREADIM*zoom) + viewport.Y()*zoom);
1878 }
1879 
DrawCircle(QPoint origin)1880 void RenderArea::DrawCircle(QPoint origin)
1881 {
1882     // Draw a circle in the RenderArea using openGL
1883     float DEG2RAD = 3.14159f/180.0f;
1884     float r = (float)VRADIUS/zoom;
1885     glBegin(GL_TRIANGLE_FAN);
1886     for (int i = 0; i < 360; i++)
1887     {
1888         float degInRad = i*DEG2RAD;
1889         glVertex3f(origin.x() + cos(degInRad)*r,origin.y() + sin(degInRad)*r,2.0f);
1890     }
1891     glEnd();
1892 }
1893 
UpdateBoundingArea(QPoint topLeft,QPoint topRight)1894 void RenderArea::UpdateBoundingArea(QPoint topLeft, QPoint topRight)
1895 {
1896     // Update the bounding box (selection rectangle) of the selected faces/vertices
1897     if (topLeft.x() < selStart.x()) selStart.setX(topLeft.x());
1898     if (topLeft.y() < selStart.y()) selStart.setY(topLeft.y());
1899     if (topRight.x() > selEnd.x()) selEnd.setX(topRight.x());
1900     if (topRight.y() > selEnd.y()) selEnd.setY(topRight.y());
1901 }
1902 
1903 // Import the face selected from the meshlab GLArea in the pluging
ImportSelection()1904 void RenderArea::ImportSelection()
1905 {
1906     for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearUserBit(selBit);
1907     selStart = QPoint(MAX,MAX);
1908     selEnd = QPoint(-MAX,-MAX);
1909     CMeshO::FaceIterator fi;
1910     for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi)
1911     {
1912         if ((*fi).IsS() && !(*fi).IsD())
1913         {
1914             if (!selected) selected = true;
1915             (*fi).SetUserBit(selBit);
1916             QPoint a = ToScreenSpace((*fi).WT(0).u(), (*fi).WT(0).v());
1917             QPoint b = ToScreenSpace((*fi).WT(1).u(), (*fi).WT(1).v());
1918             QPoint c = ToScreenSpace((*fi).WT(2).u(), (*fi).WT(2).v());
1919             SetUpRegion(a, b, c);
1920         }
1921     }
1922     if (selected)
1923     {
1924         selection = QRect(selStart, selEnd);
1925         UpdateSelectionArea(0,0);
1926         originR.moveCenter(ToScreenSpace(origin.x(), origin.y()));
1927         origin = ToUVSpace(originR.center().x(), originR.center().y());
1928     }
1929     ChangeMode(EDITFACEMODE);
1930     this->update();
1931 }
1932 
CountVertexes()1933 void RenderArea::CountVertexes()
1934 {
1935     // Count the number of selected UV vertices (not so easy...)
1936     VCount = 0;
1937     collapse1 = 0;
1938     collapse2 = 0;
1939     CMeshO::FaceIterator fi;
1940     vector< TexCoord2<float> > tmpCoord = vector< TexCoord2<float> >();
1941     for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi)
1942     {
1943         if ((*fi).WT(0).n() == textNum)
1944         {
1945             for (int j = 0; j < 3; j++)
1946             {
1947                 if ((*fi).V(j)->IsUserBit(selVertBit))
1948                 {
1949                     if (!isInside(tmpCoord, (*fi).WT(j)) && areaUV.contains(QPointF((*fi).WT(j).u(), (*fi).WT(j).v())))
1950                     {
1951                         VCount++;
1952                         if (collapse1 == 0) {collapse1 = (*fi).V(j); vc1 = (*fi).WT(j); }
1953                         else if (collapse2 == 0) {collapse2 = (*fi).V(j); vc2 = (*fi).WT(j); }
1954                         tmpCoord.push_back((*fi).WT(j));
1955                     }
1956                 }
1957             }
1958         }
1959     }
1960 }
1961 
UpdateUnifyTopology()1962 void RenderArea::UpdateUnifyTopology()
1963 {
1964     // Update the topology needed for unify of edge
1965     vcg::tri::UpdateTopology<CMeshO>::FaceFaceFromTexCoord(model->cm);
1966     vcg::tri::UpdateTopology<CMeshO>::VertexFace(model->cm);
1967     vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromFF(model->cm);
1968     vcg::tri::UpdateFlags<CMeshO>::VertexBorderFromFaceBorder(model->cm);
1969 }
1970 
isInside(vector<TexCoord2<float>> tmpCoord,TexCoord2<float> act)1971 bool RenderArea::isInside(vector<TexCoord2<float> > tmpCoord, TexCoord2<float> act)
1972 {
1973     // Support function for search in a vector
1974     for (unsigned i = 0; i < tmpCoord.size(); i++)
1975     {
1976         if (tmpCoord[i] == act) return true;
1977     }
1978     return false;
1979 }
1980 
isInside(CFaceO * face)1981 bool RenderArea::isInside(CFaceO* face)
1982 {
1983     for (int h = 0; h < banList.size(); h++)
1984     {
1985         if (face == banList[h]) return true;
1986     }
1987     return false;
1988 }
1989 
ShowFaces()1990 void RenderArea::ShowFaces()
1991 {
1992     // Set up model for display the selected faces
1993     for (unsigned i = 0; i < model->cm.face.size(); i++)
1994     {
1995         if (model->cm.face[i].IsUserBit(selBit)) model->cm.face[i].SetS();
1996         else model->cm.face[i].ClearS();
1997     }
1998     emit UpdateModel();
1999 }
2000 
2001 // Reset the position of the viewport
ResetPosition()2002 void RenderArea::ResetPosition()
2003 {
2004     zoom = 1;
2005     ResetTrack(true);
2006     if (selected) RecalculateSelectionArea();
2007     else if (selectedV) UpdateVertexSelection();
2008     this->update();
2009 }
2010