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