#include #include "renderarea.h" #include "textureeditor.h" #include #include #include #define SELECTIONRECT 100 #define ORIGINRECT 200 #define MAX 100000 #define NOSEL -1 #define AREADIM 400 #define HRECT 6 #define MINZOOM 0.1 #define MAXZOOM 7 RenderArea::RenderArea(QWidget *parent, QString textureName, MeshModel *m, unsigned tnum) : QGLWidget(parent) { antialiased = true; setBackgroundRole(QPalette::Base); setAutoFillBackground(true); image = QImage(); if(textureName != QString()) { if (QFile(textureName).exists()) image = QImage(textureName); else textureName = QString(); } textNum = tnum; model = m; // Init oldX = 0; oldY = 0; viewport = vcg::Point2f(0,0); tmpX = 0; tmpY = 0; tb = new Trackball(); tb->center = Point3f(0, 0, 0); tb->radius = 1; panX = 0; panY = 0; oldPX = 0; oldPY = 0; posVX = 0; posVY = 0; brush = QBrush(Qt::green); mode = View; editMode = Scale; origin = QPointF(); start = QPoint(); end = QPoint(); selectMode = Area; selBit = CFaceO::NewBitFlag(); selVertBit = CVertexO::NewBitFlag(); selected = false; selectedV = false; vertRect = QRect(0,0,RADIUS,RADIUS); selRect = vector(); for (int i = 0; i < 4; i++) selRect.push_back(QRect(0,0,RECTDIM,RECTDIM)); selStart = QPoint(0,0); selEnd = QPoint(0,0); degree = 0.0f; highlighted = NOSEL; pressed = NOSEL; posX = 0; posY = 0; oScale = QPointF(0,0); scaleX = 1; scaleY = 1; orX = 0; orY = 0; initVX = 0; initVY = 0; zoom = 1; rot = QImage(QString(":/images/rotate.png")); scal = QImage(QString(":/images/scale.png")); this->setMouseTracking(true); this->setCursor(Qt::PointingHandCursor); this->setAttribute(Qt::WA_NoSystemBackground); this->setAttribute(Qt::WA_KeyCompression, true); this->setFocusPolicy(Qt::ClickFocus); } RenderArea::~RenderArea() { CFaceO::DeleteBitFlag(selBit); CVertexO::DeleteBitFlag(selVertBit); } void RenderArea::setPen(const QPen &pen) { this->pen = pen; update(); } void RenderArea::setBrush(const QBrush &brush) { this->brush = brush; update(); } void RenderArea::setAntialiased(bool antialiased) { this->antialiased = antialiased; update(); } void RenderArea::setTexture(QString path) { image = QImage(path); fileName = path; } void RenderArea::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setPen(QPen(brush,2)); painter.setBrush(brush); painter.setRenderHint(QPainter::Antialiasing, antialiased); painter.setRenderHint(QPainter::SmoothPixmapTransform, true); //painter.begin(painter.device()); // Initialize a GL context tb->GetView(); tb->Apply(true); maxX = 0; maxY = 0; minX = 0; minY = 0; if (model->cm.HasPerWedgeTexCoord() && image != QImage()) { glEnable(GL_COLOR_LOGIC_OP); glEnable(GL_DEPTH_TEST); glLineWidth(1); for (unsigned i = 0; i < model->cm.face.size(); i++) { glLogicOp(GL_XOR); glColor3f(1,1,1); // First draw the model in u,v space if (model->cm.face[i].WT(0).n() == textNum) { // While drawning, it counts the number of 'planes' 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++; 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++; 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--; 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--; // Draw the edge of faces glBegin(GL_LINE_LOOP); for (int j = 0; j < 3; j++) { if (mode != EditVert) { if (!model->cm.face[i].IsUserBit(selBit)) glVertex3f(model->cm.face[i].WT(j).u() * AREADIM , AREADIM - (model->cm.face[i].WT(j).v() * AREADIM), 1); else if (editMode == Scale) glVertex3f((oScale.x() + (model->cm.face[i].WT(j).u() - oScale.x()) * scaleX) * AREADIM - panX/zoom, AREADIM - ((oScale.y() + (model->cm.face[i].WT(j).v() - oScale.y()) * scaleY) * AREADIM) - panY/zoom, 1); 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, 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); } else { 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)) 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, 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); else glVertex3f(model->cm.face[i].WT(j).u() * AREADIM , AREADIM - (model->cm.face[i].WT(j).v() * AREADIM), 1); } } glEnd(); // Draw the selected faces if (selected && model->cm.face[i].IsUserBit(selBit)) { glLogicOp(GL_AND); glColor3f(1,0,0); glBegin(GL_TRIANGLES); for (int j = 0; j < 3; j++) { if (editMode == Scale) glVertex3f((oScale.x() + (model->cm.face[i].WT(j).u() - oScale.x()) * scaleX) * AREADIM - panX/zoom, AREADIM - ((oScale.y() + (model->cm.face[i].WT(j).v() - oScale.y()) * scaleY) * AREADIM) - panY/zoom, 1); 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, 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); } glEnd(); } // Draw the selected vertex if (selectedV) { glDisable(GL_COLOR_LOGIC_OP); for (int j = 0; j < 3; j++) { 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)) { glColor3f(1,0,0); 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, 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)); glColor3f(0,0,0); } } glEnable(GL_COLOR_LOGIC_OP); } } } glDisable(GL_LOGIC_OP); glDisable(GL_COLOR_LOGIC_OP); // Draw the background behind the model if (minX != 0 || minY != 0 || maxX != 0 || maxY != 0) { for (int x = minX; x < maxX; x++) for (int y = minY; y < maxY; y++) painter.drawImage(QRect(x*AREADIM,-y*AREADIM,AREADIM,AREADIM),image,QRect(0,0,image.width(),image.height())); } else painter.drawImage(QRect(0,0,AREADIM,AREADIM),image,QRect(0,0,image.width(),image.height())); // and the axis, always in first plane glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0,this->width(),this->height(),0,-1,1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); // Line and text (native Qt) int w = this->visibleRegion().boundingRect().width(); int h = this->visibleRegion().boundingRect().height(); painter.drawLine(0,h,w,h); painter.drawLine(0,h,0,0); // Calculate the coords and draw it float ox = (float)-viewport.X()*zoom/(AREADIM*zoom), oy = (float)(AREADIM*zoom - h + viewport.Y()*zoom)/(AREADIM*zoom); /*O:*/painter.drawText(TRANSLATE, h - TRANSLATE, QString("(%1,%2)").arg(ox).arg(oy)); /*Y:*/painter.drawText(TRANSLATE, TRANSLATE*3, QString("(%1,%2)").arg(ox).arg((float)(AREADIM*zoom + viewport.Y()*zoom)/(AREADIM*zoom))); /*X:*/painter.drawText(w - TRANSLATE*18, h - TRANSLATE, QString("(%1,%2)").arg((float)(w-viewport.X()*zoom)/(AREADIM*zoom)).arg(oy)); painter.drawText(TRANSLATE, TRANSLATE*6, QString("V")); painter.drawText(w - TRANSLATE*23, h - TRANSLATE, QString("U")); // Draw the rectangle of selection if (start != QPoint() && end != QPoint()) { painter.setPen(QPen(QBrush(Qt::gray),1)); painter.setBrush(QBrush(Qt::NoBrush)); painter.drawRect(area); } if (selection != QRect() && (mode == Edit || mode == EditVert)) { // The rectangle of editing painter.setPen(QPen(QBrush(Qt::yellow),2)); painter.setBrush(QBrush(Qt::NoBrush)); if (mode == Edit) { painter.drawRect(QRect(selection.x() - posX, selection.y() - posY, selection.width(), selection.height())); } else { painter.drawRect(QRect(selection.x() - posVX, selection.y() - posVY, selection.width(), selection.height())); /*painter.fillRect(QRect(selection.x() - HRECT/2 - posVX + selection.width()/2, selection.y() - HRECT/2 - posVY, HRECT, HRECT), QBrush(Qt::black)); painter.fillRect(QRect(selection.x() - HRECT/2 - posVX, selection.y() - HRECT/2 - posVY + selection.height()/2, HRECT, HRECT), QBrush(Qt::black)); painter.fillRect(QRect(selection.x() - HRECT/2 - posVX + selection.width(), selection.y() + selection.height()/2 - HRECT/2 - posVY, HRECT, HRECT), QBrush(Qt::black)); painter.fillRect(QRect(selection.x() + selection.width()/2 - HRECT/2 - posVX, selection.y() + selection.height() - HRECT/2 - posVY, HRECT, HRECT), QBrush(Qt::black)); */ } if (mode == Edit || (mode == EditVert && VCount > 1)) { // Rectangle on the corner painter.setPen(QPen(QBrush(Qt::black),1)); for (unsigned l = 0; l < selRect.size(); l++) { if (l == highlighted) painter.setBrush(QBrush(Qt::yellow)); else painter.setBrush(QBrush(Qt::NoBrush)); painter.drawRect(selRect[l]); if (editMode == Scale && mode == Edit) painter.drawImage(selRect[l],scal,QRect(0,0,scal.width(),scal.height())); else painter.drawImage(selRect[l],rot,QRect(0,0,rot.width(),rot.height())); } // and the origin of the rotation if ((editMode == Rotate && mode == Edit) || mode == EditVert) { painter.setPen(QPen(QBrush(Qt::black),1)); if (highlighted == ORIGINRECT) painter.setBrush(QBrush(Qt::blue)); else painter.setBrush(QBrush(Qt::yellow)); if (mode == Edit) painter.drawEllipse(QRect(originR.x() - posX - orX, originR.y() - posY - orY, RADIUS, RADIUS)); else painter.drawEllipse(QRect(originR.x() - posVX - orX, originR.y() - posVY - orY, RADIUS, RADIUS)); } } } glDisable(GL_LOGIC_OP); glPopAttrib(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } else painter.drawText(TEXTX, TEXTY, tr("NO TEXTURE")); painter.setPen(palette().dark().color()); painter.setBrush(Qt::NoBrush); //painter.end(); } // Mouse Event: void RenderArea::mousePressEvent(QMouseEvent *e) { if ((mode == Edit || mode == EditVert) && highlighted == NOSEL) { this->ChangeMode(3); pressed = NOSEL; selected = false; selectedV = false; selVertBit = CVertexO::NewBitFlag(); selBit = CFaceO::NewBitFlag(); } switch(mode) { case View: oldX = e->x(); oldY = e->y(); tmpX = viewport.X(); tmpY = viewport.Y(); tb->MouseDown(e->x(), AREADIM-e->y(), QT2VCG(e->button(), e->modifiers())); this->update(); break; case Edit: tpanX = e->x(); tpanY = e->y(); pressed = highlighted; if (highlighted > NOSEL && highlighted < selRect.size() && mode == Edit) { rectX = selRect[highlighted].center().x(); rectY = selRect[highlighted].center().y(); oldSRX = selection.width(); oldSRY = selection.height(); scaleX = 1; scaleY = 1; int perno; if (highlighted == 0) perno = 3; else if (highlighted == 1) perno = 2; else if (highlighted == 2) perno = 1; else perno = 0; oScale = ToUVSpace(selRect[perno].center().x(), selRect[perno].center().y()); B2 = (float)(rectX - originR.center().x())*(rectX - originR.center().x()) + (rectY - originR.center().y())*(rectY - originR.center().y()); Rm = (float)(rectY - originR.center().y()) / (rectX - originR.center().x()); Rq = (float) rectY - Rm * rectX; } case EditVert: tpanX = e->x(); tpanY = e->y(); if (highlighted > NOSEL && highlighted < selRect.size()) { rectX = selRect[highlighted].center().x(); rectY = selRect[highlighted].center().y(); int perno; if (highlighted == 0) perno = 3; else if (highlighted == 1) perno = 2; else if (highlighted == 2) perno = 1; else perno = 0; B2 = (float)(rectX - originR.center().x())*(rectX - originR.center().x()) + (rectY - originR.center().y())*(rectY - originR.center().y()); Rm = (float)(rectY - originR.center().y()) / (rectX - originR.center().x()); Rq = (float) rectY - Rm * rectX; } pressed = highlighted; break; case Select: start = e->pos(); end = e->pos(); break; } } void RenderArea::mouseReleaseEvent(QMouseEvent *e) { switch(mode) { case View: if (selection != QRect()) { UpdateSelectionArea((viewport.X() - initVX)*zoom, (viewport.Y() - initVY)*zoom); originR.moveCenter(QPoint(originR.x() + (viewport.X() - initVX)*zoom, originR.y() + (viewport.Y() - initVY)*zoom)); origin = ToUVSpace(originR.center().x(), originR.center().y()); } initVX = viewport.X(); initVY = viewport.Y(); break; case Edit: oldPX = panX; oldPY = panY; if (pressed == ORIGINRECT) // Drag origin -> Update the position of the rectangle of rotation and the real point in UV { originR = QRect(originR.x() - posX - orX, originR.y() - posY - orY, RADIUS, RADIUS); origin = ToUVSpace(originR.center().x(), originR.center().y()); orX = 0; orY = 0; } else if (pressed == SELECTIONRECT && posX != 0) // Drag selection -> Update the position of the selection area and the rotatation rect { selection = QRect(selection.x() - posX, selection.y() - posY, selection.width(), selection.height()); originR.moveCenter(QPoint(originR.center().x() - posX, originR.center().y() - posY)); origin = ToUVSpace(originR.center().x(), originR.center().y()); posX = 0; posY = 0; if (selected) UpdateUV(); } else if (pressed > NOSEL && pressed < selRect.size()) { if (editMode == Rotate) { RotateComponent(degree); RecalculateSelectionArea(); degree = 0; } else if (scaleX != 1 && scaleY != 1) { ScaleComponent(scaleX, scaleY); RecalculateSelectionArea(); scaleX = 1; scaleY = 1; oScale = QPointF(0,0); } } break; case EditVert: if (pressed == ORIGINRECT) { originR = QRect(originR.x() - posX - orX, originR.y() - posY - orY, RADIUS, RADIUS); origin = ToUVSpace(originR.center().x(), originR.center().y()); orX = 0; orY = 0; } else if (pressed == SELECTIONRECT && posVX != 0) { selection = QRect(selection.x() - posVX, selection.y() - posVY, selection.width(), selection.height()); originR.moveCenter(QPoint(originR.center().x() - posVX, originR.center().y() - posVY)); origin = ToUVSpace(originR.center().x(), originR.center().y()); if (selectedV) UpdateVertex(); } else if (pressed > NOSEL && pressed < selRect.size()) { RotateComponent(degree); UpdateVertexSelection(); UpdateSelectionAreaV(0,0); degree = 0; } break; case Select: start = QPoint(); end = QPoint(); area = QRect(); switch (selectMode) { case Area: if (selected) { selection = QRect(selStart, selEnd); UpdateSelectionArea(0,0); origin = ToUVSpace(selection.center().x(), selection.center().y()); originR = QRect(selection.center().x()-RADIUS/2, selection.center().y()-RADIUS/2, RADIUS, RADIUS); this->ChangeMode(1); this->update(selection); this->ShowFaces(); emit UpdateModel(); } break; case Connected: SelectConnectedComponent(e->pos()); if (selected) { selection = QRect(selStart, selEnd); UpdateSelectionArea(0,0); origin = ToUVSpace(selection.center().x(), selection.center().y()); originR = QRect(selection.center().x()-RADIUS/2, selection.center().y()-RADIUS/2, RADIUS, RADIUS); this->ChangeMode(1); this->update(); this->ShowFaces(); emit UpdateModel(); } break; case Vertex: if (selectedV) { CountVertexes(); selection = QRect(QPoint(selStart.x() - RADIUS/2, selStart.y() - RADIUS/2), QPoint(selEnd.x() + RADIUS/2, selEnd.y() + RADIUS/2)); if (VCount > 1) { UpdateSelectionAreaV(0,0); origin = ToUVSpace(selection.center().x(), selection.center().y()); originR = QRect(selection.center().x()-RADIUS/2, selection.center().y()-RADIUS/2, RADIUS, RADIUS); } this->ChangeMode(4); this->update(); } else this->update(); break; } break; } } void RenderArea::mouseMoveEvent(QMouseEvent *e) { if((e->buttons() & Qt::LeftButton)) { int sx = (e->x() - oldX)/zoom, sy = (e->y() - oldY)/zoom; switch(mode) { case View: tb->Translate(Point3f(- oldX + e->x(), - oldY + e->y(), zoom)); viewport = Point2f(tmpX + sx, tmpY + sy); this->update(); break; case Edit: if (pressed == SELECTIONRECT) { // Move the selection ara panX = oldPX + tpanX - e->x(); panY = oldPY + tpanY - e->y(); posX = tpanX - e->x(); posY = tpanY - e->y(); if (posX != 0 || posY != 0) { selRect[0].moveCenter(QPoint(selection.topLeft().x() - posX, selection.topLeft().y() - posY)); selRect[1].moveCenter(QPoint(selection.topRight().x() - posX, selection.topRight().y() - posY)); selRect[2].moveCenter(QPoint(selection.bottomLeft().x() - posX, selection.bottomLeft().y() - posY)); selRect[3].moveCenter(QPoint(selection.bottomRight().x() - posX, selection.bottomRight().y() - posY)); } this->update(); } else if (pressed == ORIGINRECT) { // Move the origin rect inside the selection area orX = tpanX - e->x(); /*int tx = originR.center().x() - orX; if (tx < selection.x()) orX = - selection.x() + originR.center().x(); else if (tx > selection.x() + selection.width()) orX = originR.center().x() - (selection.x() + selection.width()); */ orY = tpanY - e->y(); /*int ty = originR.y() - posY - orY; if (ty < selection.y()) orY = - selection.y() + originR.center().y(); else if (ty > selection.y() + selection.height()) orY = originR.center().y() - (selection.y() + selection.height()); */ this->update(originR); } else if (pressed > NOSEL && pressed < selRect.size()) { if (editMode == Scale) HandleScale(e->pos()); else HandleRotate(e->pos()); } break; case EditVert: if (pressed == SELECTIONRECT) { // Move the selection ara posVX = tpanX - e->x(); posVY = tpanY - e->y(); if (posVX != 0 || posVY != 0) { selRect[0].moveBottomRight(QPoint(selection.topLeft().x() - posVX, selection.topLeft().y() - posVY)); selRect[1].moveBottomLeft(QPoint(selection.topRight().x() - posVX, selection.topRight().y() - posVY)); selRect[2].moveTopRight(QPoint(selection.bottomLeft().x() - posVX, selection.bottomLeft().y() - posVY)); selRect[3].moveTopLeft(QPoint(selection.bottomRight().x() - posVX, selection.bottomRight().y() - posVY)); } } else if (pressed > NOSEL && pressed < selRect.size()) { HandleRotate(e->pos()); } else if (pressed == ORIGINRECT) { orX = tpanX - e->x(); orY = tpanY - e->y(); this->update(originR); } this->update(); break; case Select: if (selectMode != Connected) { end = e->pos(); int x1, x2, y1, y2; if (start.x() < end.x()) {x1 = start.x(); x2 = end.x();} else {x1 = end.x(); x2 = start.x();} if (start.y() < end.y()) {y1 = start.y(); y2 = end.y();} else {y1 = end.y(); y2 = start.y();} area = QRect(x1,y1,x2-x1,y2-y1); if (selectMode == Area) SelectFaces(); else SelectVertexes(); this->update(area); } break; } } else { if (mode == Edit || mode == EditVert) { for (unsigned y = 0; y < selRect.size(); y++) { if (selRect[y].contains(e->pos()) && (mode == Edit || (mode == EditVert && VCount > 1))) { if (highlighted != y) this->update(selRect[y]); highlighted = y; return; } } if (originR.contains(e->pos()) && ((mode == Edit && editMode == Rotate) || mode == EditVert)) { if (highlighted != ORIGINRECT) this->update(originR); highlighted = ORIGINRECT; return; } if (selection.contains(e->pos())) { if (highlighted == ORIGINRECT) this->update(originR); else if (highlighted < selRect.size()) this->update(selRect[highlighted]); highlighted = SELECTIONRECT; return; } if (highlighted != NOSEL) { if (highlighted == ORIGINRECT) this->update(originR); else if (highlighted < selRect.size()) this->update(selRect[highlighted]); } highlighted = NOSEL; } } } void RenderArea::mouseDoubleClickEvent(QMouseEvent *e) { switch(mode) { case View: // Center the screen on the mouse click position viewport = Point2f(viewport.X() - e->x()/zoom + (this->visibleRegion().boundingRect().width()/zoom)/2, viewport.Y() - e->y()/zoom + (this->visibleRegion().boundingRect().height()/zoom)/2); oldX = 0; oldY = 0; tb->track.SetTranslate(Point3f(viewport.X(), viewport.Y(), 1)); tb->Scale(zoom); this->update(); break; case Edit: // Change edit mode if (selection.contains(e->pos())) { if (editMode == Rotate) editMode = Scale; else editMode = Rotate; this->update(); } break; } } void RenderArea::wheelEvent(QWheelEvent*e) { // Handle the zoom for any mode int cwx = viewport.X() - (this->visibleRegion().boundingRect().width()/zoom)/2; int cwy = viewport.Y() - (this->visibleRegion().boundingRect().height()/zoom)/2; bool scale = false; if (e->delta() > 0) { if (zoom/0.75 < MAXZOOM) { zoom /= 0.75; scale = true; } } else if (zoom*0.75 > MINZOOM) { zoom *= 0.75; scale = true; } if (scale) { // Change the viewport, putting the center of the screen on the mouseposition cwx += (this->visibleRegion().boundingRect().width()/zoom)/2; cwy += (this->visibleRegion().boundingRect().height()/zoom)/2; viewport = Point2f(cwx, cwy); ResetTrack(false); tb->Scale(zoom); if (selectedV) { UpdateVertexSelection(); UpdateSelectionAreaV(0,0); } else { RecalculateSelectionArea(); UpdateSelectionArea(0,0); } originR.moveCenter(ToScreenSpace(origin.x(), origin.y())); initVX = viewport.X(); initVY = viewport.Y(); this->update(); } } void RenderArea::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_H) ResetPosition(); else e->ignore(); } void RenderArea::RemapClamp() { // Remap the uv coord out of border using clamp method for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum) { model->cm.face[i].ClearUserBit(selBit); for (unsigned j = 0; j < 3; j++) { if (model->cm.face[i].WT(j).u() > 1) model->cm.face[i].WT(j).u() = 1; else if (model->cm.face[i].WT(j).u() < 0) model->cm.face[i].WT(j).u() = 0; if (model->cm.face[i].WT(j).v() > 1) model->cm.face[i].WT(j).v() = 1; else if (model->cm.face[i].WT(j).v() < 0) model->cm.face[i].WT(j).v() = 0; } } } panX = 0; panY = 0; tpanX = 0; tpanY = 0; oldPX = 0; oldPY = 0; ResetTrack(true); this->update(); emit UpdateModel(); } void RenderArea::RemapMod() { // Remap the uv coord out of border using mod function for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum) { model->cm.face[i].ClearUserBit(selBit); for (unsigned j = 0; j < 3; j++) { float u = model->cm.face[i].WT(j).u(); float v = model->cm.face[i].WT(j).v(); if (u < 0) u = u + (int)u + 1; else if (u > 1) u = u - (int)u; if (v < 0) v = v + (int)v + 1; else if (v > 1) v = v - (int)v; model->cm.face[i].WT(j).u() = u; model->cm.face[i].WT(j).v() = v; } } } panX = 0; panY = 0; tpanX = 0; tpanY = 0; oldPX = 0; oldPY = 0; ResetTrack(true); this->update(); emit UpdateModel(); } void RenderArea::ChangeMode(int index) { // Change the selection mode switch(index) { case 0: if (mode != View) { mode = View; this->setCursor(Qt::PointingHandCursor); } break; case 1: if (mode != Edit) { mode = Edit; this->setCursor(Qt::SizeAllCursor); } break; case 2: if (mode != Select) { if (selection != QRect()) { if (selectMode == Vertex) { mode = EditVert; selectedV = true; selBit = CFaceO::NewBitFlag(); } else { mode = Edit; selected = true; selVertBit = CVertexO::NewBitFlag(); } this->setCursor(Qt::SizeAllCursor); } else { mode = Select; selBit = CFaceO::NewBitFlag(); selVertBit = CVertexO::NewBitFlag(); this->setCursor(Qt::CrossCursor); } } break; case 3: // For internal use... reset the selction mode = Select; for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearUserBit(selBit); selection = QRect(); this->setCursor(Qt::CrossCursor); break; case 4: if (mode != EditVert) { if (selection != QRect()) { mode = EditVert; selectedV = true; this->setCursor(QCursor(QBitmap(":/images/sel_move.png"))); } else { mode = Select; this->setCursor(Qt::CrossCursor); } } break; } this->update(); } void RenderArea::ChangeSelectMode(int index) { // Change the function of the mouse selection switch(index) { case 0: if (selectMode != Area && selectMode != Connected) selection = QRect(); selectMode = Area; break; case 1: if (selectMode != Connected && selectMode != Area) selection = QRect(); selectMode = Connected; break; case 2: if (selectMode != Vertex) selection = QRect(); selectMode = Vertex; break; default: selectMode = Area; break; } if (selectedV && selectMode != Vertex) { areaUV = QRectF(); selVertBit = CVertexO::NewBitFlag(); selectedV = false; } if (selected && selectMode == Vertex) { selected = false; selBit = CFaceO::NewBitFlag(); for (unsigned i = 0; i < model->cm.face.size(); i++) model->cm.face[i].ClearS(); emit UpdateModel(); } } void RenderArea::RotateComponent(float theta) { // Calcolate the new position of the vertex of the selected component after a rotation. // The rotation is done around the selected point if (origin != QPoint()) { float sinv = sin(theta); float cosv = cos(theta); if (selected) { for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum && (!selected || (selected && model->cm.face[i].IsUserBit(selBit)))) for (unsigned j = 0; j < 3; j++) { float u = origin.x() + (cosv * (model->cm.face[i].WT(j).u() - origin.x()) - sinv * (model->cm.face[i].WT(j).v() - origin.y())); float v = origin.y() + (sinv * (model->cm.face[i].WT(j).u() - origin.x()) + cosv * (model->cm.face[i].WT(j).v() - origin.y())); model->cm.face[i].WT(j).u() = u; model->cm.face[i].WT(j).v() = v; } } } else if (selectedV) { for (unsigned i = 0; i < model->cm.face.size(); i++) { for (unsigned j = 0; j < 3; j++) { 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)) { float u = origin.x() + (cosv * (model->cm.face[i].WT(j).u() - origin.x()) - sinv * (model->cm.face[i].WT(j).v() - origin.y())); float v = origin.y() + (sinv * (model->cm.face[i].WT(j).u() - origin.x()) + cosv * (model->cm.face[i].WT(j).v() - origin.y())); model->cm.face[i].WT(j).u() = u; model->cm.face[i].WT(j).v() = v; } } } } this->update(); emit UpdateModel(); } } void RenderArea::ScaleComponent(float percX, float percY) { // Scale the selected component. The origin is set to the clicked point for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum && selected && model->cm.face[i].IsUserBit(selBit)) for (unsigned j = 0; j < 3; j++) { float x = oScale.x() + (model->cm.face[i].WT(j).u() - oScale.x()) * percX; float y = oScale.y() + (model->cm.face[i].WT(j).v() - oScale.y()) * percY; model->cm.face[i].WT(j).u() = x; model->cm.face[i].WT(j).v() = y; } } this->update(); emit UpdateModel(); } void RenderArea::UpdateUV() { // After a move of component, re-calculate the new UV coordinates for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum && model->cm.face[i].IsUserBit(selBit)) { for (unsigned j = 0; j < 3; j++) { model->cm.face[i].WT(j).u() = model->cm.face[i].WT(j).u() - (float)panX/(AREADIM*zoom); model->cm.face[i].WT(j).v() = model->cm.face[i].WT(j).v() + (float)panY/(AREADIM*zoom); } } } panX = 0; panY = 0; tpanX = 0; tpanY = 0; oldPX = 0; oldPY = 0; this->update(); emit UpdateModel(); } void RenderArea::UpdateVertex() { // After a move of vertex, re-calculate the new UV coordinates for (unsigned i = 0; i < model->cm.face.size(); i++) { for (unsigned j = 0; j < 3; j++) { 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)) { model->cm.face[i].WT(j).u() = model->cm.face[i].WT(j).u() - (float)posVX/(AREADIM*zoom); model->cm.face[i].WT(j).v() = model->cm.face[i].WT(j).v() + (float)posVY/(AREADIM*zoom); } } } areaUV.moveCenter(QPointF(areaUV.center().x() - (float)posVX/(AREADIM*zoom), areaUV.center().y() + (float)posVY/(AREADIM*zoom))); tpanX = 0; tpanY = 0; posVX = 0; posVY = 0; this->update(); emit UpdateModel(); } void RenderArea::ResetTrack(bool resetViewPort) { // Reset the viewport of the trackball tb->center = Point3f(0, 0, 0); tb->track.SetScale(1); if (resetViewPort) viewport = Point2f(0,0); oldX = 0; oldY = 0; tb->track.SetTranslate(Point3f(viewport.X(), viewport.Y(), 1)); } void RenderArea::SelectFaces() { // Check if a face is inside the rectangle of selection and mark it selStart = QPoint(MAX,MAX); selEnd = QPoint(-MAX,-MAX); selected = false; selection = QRect(); CMeshO::FaceIterator fi; for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi) { if ((*fi).WT(0).n() == textNum) { (*fi).ClearUserBit(selBit); QVector t = QVector(); t.push_back(ToScreenSpace((*fi).WT(0).u(), (*fi).WT(0).v())); t.push_back(ToScreenSpace((*fi).WT(1).u(), (*fi).WT(1).v())); t.push_back(ToScreenSpace((*fi).WT(2).u(), (*fi).WT(2).v())); QRegion r = QRegion(QPolygon(t)); if (r.intersects(area)) { (*fi).SetUserBit(selBit); UpdateBoundingArea(r.boundingRect().topLeft(), r.boundingRect().bottomRight()); if (!selected) selected = true; } } } } void RenderArea::SelectVertexes() { // Check if a vertex is inside the rectangle of selection selStart = QPoint(MAX,MAX); selEnd = QPoint(-MAX,-MAX); selectedV = false; selection = QRect(); QPointF a = ToUVSpace(area.x(), area.y()); QPointF b = ToUVSpace(area.bottomRight().x(),area.bottomRight().y()); areaUV = QRectF(a, QSizeF(b.x()-a.x(), b.y()-a.y())); CMeshO::FaceIterator fi; for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi) { if ((*fi).WT(0).n() == textNum) { for (int j = 0; j < 3; j++) { QPoint tmp = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v()); if (area.contains(tmp)) { (*fi).V(j)->SetUserBit(selVertBit); UpdateBoundingArea(tmp, tmp); if (!selectedV) selectedV = true; } } } } } void RenderArea::SelectConnectedComponent(QPoint e) { // Select a series of faces with the same UV coord on the edge selStart = QPoint(MAX,MAX); selEnd = QPoint(-MAX,-MAX); selected = false; selBit = CFaceO::NewBitFlag(); int index = 0; vector Q = vector(); // Search the clicked face for(unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum) { QVector t = QVector(); t.push_back(ToScreenSpace(model->cm.face[i].WT(0).u(), model->cm.face[i].WT(0).v())); t.push_back(ToScreenSpace(model->cm.face[i].WT(1).u(), model->cm.face[i].WT(1).v())); t.push_back(ToScreenSpace(model->cm.face[i].WT(2).u(), model->cm.face[i].WT(2).v())); QRegion r = QRegion(QPolygon(t)); if (r.contains(e)) { Q.push_back(&model->cm.face[i]); model->cm.face[i].SetUserBit(selBit); UpdateBoundingArea(r.boundingRect().topLeft(), r.boundingRect().bottomRight()); selected = true; break; } } } while (index < Q.size()) { for (int j = 0; j < 3; j++) { CFaceO* p = Q[index]->FFp(j); if (!p->IsUserBit(selBit) && ( (Q[index]->WT(0) == p->WT(0) || Q[index]->WT(0) == p->WT(1) || Q[index]->WT(0) == p->WT(2)) || (Q[index]->WT(1) == p->WT(0) || Q[index]->WT(1) == p->WT(1) || Q[index]->WT(1) == p->WT(2)) || (Q[index]->WT(2) == p->WT(0) || Q[index]->WT(2) == p->WT(1) || Q[index]->WT(2) == p->WT(2)))) { p->SetUserBit(selBit); Q.push_back(p); QPoint tmp = ToScreenSpace(p->WT(j).u(), p->WT(j).v()); UpdateBoundingArea(tmp, tmp); } } index++; } } void RenderArea::ClearSelection() { // Clear every selection selBit = CFaceO::NewBitFlag(); selVertBit = CVertexO::NewBitFlag(); selection = QRect(); } void RenderArea::InvertSelection() { // Invert selected faces if (selected) { for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum) { if (model->cm.face[i].IsUserBit(selBit)) model->cm.face[i].ClearUserBit(selBit); else model->cm.face[i].SetUserBit(selBit); } } RecalculateSelectionArea(); originR.moveCenter(selection.center()); origin = ToUVSpace(originR.center().x(), originR.center().y()); this->update(); } else if (selectedV) { for (unsigned i = 0; i < model->cm.vert.size(); i++) { if (model->cm.vert[i].IsUserBit(selVertBit)) model->cm.vert[i].ClearUserBit(selVertBit); else model->cm.vert[i].SetUserBit(selVertBit); } UpdateVertexSelection(); this->update(); } } void RenderArea::Flip(bool mode) { if (selected) { QPointF mid = ToUVSpace(selection.center().x(), selection.center().y()); for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].WT(0).n() == textNum) { if (model->cm.face[i].IsUserBit(selBit)) { for (int j = 0; j < 3; j++) { if (mode) model->cm.face[i].WT(j).u() = 2.0f * mid.x() - model->cm.face[i].WT(j).u(); else model->cm.face[i].WT(j).v() = 2.0f * mid.y() - model->cm.face[i].WT(j).v(); } } } } RecalculateSelectionArea(); this->update(); } } void RenderArea::UnifyCouple() { // Calculate the average coordinates and unify a couple of vertexes if (VCount == 2) { float tu = (vc1.u() + vc2.u())/2.0; float tv = (vc1.v() + vc2.v())/2.0; for (unsigned i = 0; i < model->cm.face.size(); i++) { for (unsigned j = 0; j < 3; j++) { if (model->cm.face[i].V(j) == collapse1 || model->cm.face[i].V(j) == collapse2) { model->cm.face[i].WT(j).u() = tu; model->cm.face[i].WT(j).v() = tv; } } } selectedV = false; selVertBit = CVertexO::NewBitFlag(); areaUV = QRectF(); selection = QRect(); this->ChangeMode(2); this->update(); emit UpdateModel(); } } void RenderArea::UnifySet() { // Unify a set of vertexes // <------ } void RenderArea::HandleScale(QPoint e) { // Move the rectangle of scaling and resize the selction area int tx = rectX - tpanX + e.x(); int ty = rectY - tpanY + e.y(); switch(highlighted) { case 0: // Top Left if (tx > selection.x() + selection.width() - RECTDIM) tx = selection.x() + selection.width() - RECTDIM; if (ty > selection.y() + selection.height() - RECTDIM) ty = selection.y() + selection.height() - RECTDIM; selRect[0].moveCenter(QPoint(tx, ty)); //selRect[2].moveCenter(QPoint(tx, selRect[2].center().y())); // THERE IS A BUG IN QT: movecenter doesn't work //selRect[1].moveCenter(QPoint(selRect[1].center().x(),ty)); if coords are negative....... selRect[2] = QRect(tx - RECTDIM/2, selRect[2].y(), RECTDIM, RECTDIM); selRect[1] = QRect(selRect[1].x(), ty - RECTDIM/2, RECTDIM, RECTDIM); selection.setTopLeft(selRect[0].center()); selection.setBottomLeft(selRect[2].center()); selection.setTopRight(selRect[1].center()); this->update(selRect[1]); break; case 1: // Top Right if (tx < selection.x() + RECTDIM) tx = selection.x() + RECTDIM; if (ty > selection.y() + selection.height() - RECTDIM) ty = selection.y() + selection.height() - RECTDIM; selRect[1].moveCenter(QPoint(tx, ty)); //selRect[3].moveCenter(QPoint(tx, selRect[3].center().y())); //selRect[0].moveCenter(QPoint(selRect[0].center().x(), ty)); selRect[3] = QRect(tx - RECTDIM/2, selRect[3].y(), RECTDIM, RECTDIM); selRect[0] = QRect(selRect[0].x(), ty - RECTDIM/2, RECTDIM, RECTDIM); selection.setTopRight(selRect[1].center()); selection.setTopLeft(selRect[0].center()); selection.setBottomRight(selRect[3].center()); this->update(selRect[0]); break; case 2: // Bottom Left if (tx > selection.x() + selection.width() - RECTDIM) tx = selection.x() + selection.width() - RECTDIM; if (ty < selection.y() + RECTDIM) ty = selection.y() + RECTDIM; selRect[2].moveCenter(QPoint(tx, ty)); //selRect[0].moveCenter(QPoint(tx, selRect[0].center().y())); //selRect[3].moveCenter(QPoint(selRect[3].center().x(), ty)); selRect[0] = QRect(tx - RECTDIM/2, selRect[0].y(), RECTDIM, RECTDIM); selRect[3] = QRect(selRect[3].x(), ty - RECTDIM/2, RECTDIM, RECTDIM); selection.setTopLeft(selRect[0].center()); selection.setBottomLeft(selRect[2].center()); selection.setBottomRight(selRect[3].center()); this->update(selRect[3]); break; case 3: // Bottom Right if (tx < selection.x() + RECTDIM) tx = selection.x() + RECTDIM; if (ty < selection.y() + RECTDIM) ty = selection.y() + RECTDIM; selRect[3].moveCenter(QPoint(tx, ty)); //selRect[1].moveCenter(QPoint(tx, selRect[1].center().y())); //selRect[2].moveCenter(QPoint(selRect[2].center().x(), ty)); selRect[1] = QRect(tx - RECTDIM/2, selRect[1].y(), RECTDIM, RECTDIM); selRect[2] = QRect(selRect[2].x(), ty - RECTDIM/2, RECTDIM, RECTDIM); selection.setTopRight(selRect[1].center()); selection.setBottomLeft(selRect[2].center()); selection.setBottomRight(selRect[3].center()); this->update(selRect[2]); break; } this->update(selRect[highlighted]); this->update(selRect[(highlighted+2)%selRect.size()]); originR.moveCenter(selection.center()); origin = ToUVSpace(originR.center().x(), originR.center().y()); // calculate scaling scaleX = (float)selection.width() / oldSRX; scaleY = (float)selection.height() / oldSRY; this->update(selection); } void RenderArea::HandleRotate(QPoint e) { // Calculate the angle of rotazion float A2 = (e.x() - originR.center().x())*(e.x() - originR.center().x()) + (e.y() - originR.center().y())*(e.y() - originR.center().y()); float C2 = (rectX - e.x())*(rectX - e.x()) + (rectY - e.y()) * (rectY -e.y()); degree = acos((C2 - A2 - B2) / (-2*sqrt(A2)*sqrt(B2))); float ny = (float) Rm * e.x() + Rq; switch(highlighted) { case 0: if (ny > e.y()) degree = -degree; break; case 1: if (ny < e.y()) degree = -degree; break; case 2: if (ny > e.y()) degree = -degree; break; case 3: if (ny < e.y()) degree = -degree; break; } this->update(); } void RenderArea::RecalculateSelectionArea() { // Find the new size of the selection rectangle after a rotation or a scale selStart = QPoint(MAX,MAX); selEnd = QPoint(-MAX,-MAX); CMeshO::FaceIterator fi; for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi) { if ((*fi).IsUserBit(selBit)) { QVector t = QVector(); t.push_back(ToScreenSpace((*fi).WT(0).u(), (*fi).WT(0).v())); t.push_back(ToScreenSpace((*fi).WT(1).u(), (*fi).WT(1).v())); t.push_back(ToScreenSpace((*fi).WT(2).u(), (*fi).WT(2).v())); QRegion r = QRegion(QPolygon(t)); UpdateBoundingArea(r.boundingRect().topLeft(), r.boundingRect().bottomRight()); } } if (selected) { selection = QRect(selStart, selEnd); UpdateSelectionArea(0,0); } } void RenderArea::UpdateSelectionArea(int x, int y) { // Update the buttons of the selection area selection.moveCenter(QPoint(selection.center().x() + x, selection.center().y() + y)); selRect[0].moveCenter(selection.topLeft()); selRect[1].moveCenter(selection.topRight()); selRect[2].moveCenter(selection.bottomLeft()); selRect[3].moveCenter(selection.bottomRight()); } void RenderArea::UpdateSelectionAreaV(int x, int y) { // Update the buttons of the selection area for vertexes selection.moveCenter(QPoint(selection.center().x() + x, selection.center().y() + y)); selRect[0].moveBottomRight(selection.topLeft()); selRect[1].moveBottomLeft(selection.topRight()); selRect[2].moveTopRight(selection.bottomLeft()); selRect[3].moveTopLeft(selection.bottomRight()); } void RenderArea::UpdateVertexSelection() { // Recalcultate the rectangle for selection of vertexes selStart = QPoint(MAX,MAX); selEnd = QPoint(-MAX,-MAX); selectedV = false; selection = QRect(); CMeshO::FaceIterator fi; for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi) { if ((*fi).WT(0).n() == textNum) { for (int j = 0; j < 3; j++) { QPoint tmp = ToScreenSpace((*fi).WT(j).u(), (*fi).WT(j).v()); if ((*fi).V(j)->IsUserBit(selVertBit)) { UpdateBoundingArea(tmp,tmp); if (!selectedV) selectedV = true; } } } } selection = QRect(QPoint(selStart.x() - VRADIUS, selStart.y() - VRADIUS), QPoint(selEnd.x() + VRADIUS, selEnd.y() + VRADIUS)); QPointF a = ToUVSpace(selection.x(), selection.y()); QPointF b = ToUVSpace(selection.bottomRight().x(),selection.bottomRight().y()); areaUV = QRectF(a, QSizeF(b.x()-a.x(), b.y()-a.y())); } QPointF RenderArea::ToUVSpace(int x, int y) { // Convert a point from screen-space to uv-space return QPointF((float)(x - viewport.X()*zoom)/(AREADIM*zoom), (float)(AREADIM*zoom - y + viewport.Y()*zoom)/(AREADIM*zoom)); } QPoint RenderArea::ToScreenSpace(float u, float v) { // Convert a point from uv-space to screen space return QPoint(u * AREADIM*zoom + viewport.X()*zoom, AREADIM*zoom - (v * AREADIM*zoom) + viewport.Y()*zoom); } void RenderArea::DrawCircle(QPoint origin) { // Draw a circle float DEG2RAD = 3.14159f/180.0f; float r = (float)VRADIUS/zoom; glBegin(GL_TRIANGLE_FAN); for (int i = 0; i < 360; i++) { float degInRad = i*DEG2RAD; glVertex3f(origin.x() + cos(degInRad)*r,origin.y() + sin(degInRad)*r,2.0f); } glEnd(); } void RenderArea::UpdateBoundingArea(QPoint topLeft, QPoint topRight) { // Update the bounding box (selection rectangle) of the selected faces/vertexes if (topLeft.x() < selStart.x()) selStart.setX(topLeft.x()); if (topLeft.y() < selStart.y()) selStart.setY(topLeft.y()); if (topRight.x() > selEnd.x()) selEnd.setX(topRight.x()); if (topRight.y() > selEnd.y()) selEnd.setY(topRight.y()); } void RenderArea::ImportSelection() { selBit = CFaceO::NewBitFlag(); selStart = QPoint(MAX,MAX); selEnd = QPoint(-MAX,-MAX); CMeshO::FaceIterator fi; for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi) { if ((*fi).IsS()) { if (!selected) selected = true; (*fi).SetUserBit(selBit); QVector t = QVector(); t.push_back(ToScreenSpace((*fi).WT(0).u(), (*fi).WT(0).v())); t.push_back(ToScreenSpace((*fi).WT(1).u(), (*fi).WT(1).v())); t.push_back(ToScreenSpace((*fi).WT(2).u(), (*fi).WT(2).v())); QRegion r = QRegion(QPolygon(t)); UpdateBoundingArea(r.boundingRect().topLeft(), r.boundingRect().bottomRight()); } } if (selected) { selection = QRect(selStart, selEnd); UpdateSelectionArea(0,0); originR.moveCenter(ToScreenSpace(origin.x(), origin.y())); origin = ToUVSpace(originR.center().x(), originR.center().y()); } ChangeMode(1); this->update(); } void RenderArea::CountVertexes() { // Count the number of selected UV vertexes (not so easy) VCount = 0; collapse1 = 0; collapse2 = 0; CMeshO::FaceIterator fi; vector< TexCoord2 > tmpCoord = vector< TexCoord2 >(); for(fi = model->cm.face.begin(); fi != model->cm.face.end(); ++fi) { if ((*fi).WT(0).n() == textNum) { for (int j = 0; j < 3; j++) { if ((*fi).V(j)->IsUserBit(selVertBit)) { if (!isInside(tmpCoord, (*fi).WT(j)) && areaUV.contains(QPointF((*fi).WT(j).u(), (*fi).WT(j).v()))) { VCount++; if (collapse1 == 0) {collapse1 = (*fi).V(j); vc1 = (*fi).WT(j); } else if (collapse2 == 0) {collapse2 = (*fi).V(j); vc2 = (*fi).WT(j); } tmpCoord.push_back((*fi).WT(j)); } } } } } } bool RenderArea::isInside(vector > tmpCoord, TexCoord2 act) { // Support function for search in a vector for (unsigned i = 0; i < tmpCoord.size(); i++) { if (tmpCoord[i] == act) return true; } return false; } void RenderArea::ShowFaces() { // Set up model for display the selected faces for (unsigned i = 0; i < model->cm.face.size(); i++) { if (model->cm.face[i].IsUserBit(selBit)) model->cm.face[i].SetS(); else model->cm.face[i].ClearS(); } } void RenderArea::ResetPosition() { // Reset the position of the viewport zoom = 1; ResetTrack(true); if (selected) RecalculateSelectionArea(); else if (selectedV) UpdateVertexSelection(); this->update(); }