/**************************************************************************** * MeshLab o o * * An extendible mesh processor o o * * _ O _ * * Copyright(C) 2005, 2009 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /* A class implementing Meshlab's Edit interface that is for picking points in 3D * * * @author Oscar Barney */ #include #include #include "editpickpoints.h" #include #include #include #include #include #include using namespace vcg; #define PI 3.14159265 EditPickPointsPlugin::EditPickPointsPlugin() { // initialize to false so we don't end up collecting some weird point in the beginning registerPoint = false; moveSelectPoint = false; pickPointsDialog = 0; currentModel = 0; overrideCursorShape = 0; } //Constants const QString EditPickPointsPlugin::Info() { return tr("Pick and save 3D points on the mesh"); } QString EditPickPointsPlugin::pluginName() const { return "EditPickPoints"; } //called void EditPickPointsPlugin::Decorate(MeshModel &mm, GLArea *gla, QPainter *painter) { //qDebug() << "Decorate " << mm.fileName.c_str() << " ..." << mm.cm.fn; if (gla != glArea || mm.cm.fn < 1) { //qDebug() << "GLarea is different or no faces!!! "; return; } //make sure we picking points on the right meshes! if (&mm != currentModel) { //now that were are ending tell the dialog to save any points it has to metadata pickPointsDialog->savePointsToMetaData(); //set the new mesh model pickPointsDialog->setCurrentMeshModel(&mm, gla); currentModel = &mm; } //We have to calculate the position here because it doesnt work in the mouseEvent functions for some reason Point3m pickedPoint; if (moveSelectPoint) { /* qDebug("Found point for move %i %i -> %f %f %f", currentMousePosition.x(), currentMousePosition.y(), pickedPoint[0], pickedPoint[1], pickedPoint[2]); */ //let the dialog know that this was the pointed picked in case it wants the information bool picked = Pick(currentMousePosition.x(), currentMousePosition.y(), pickedPoint); pickPointsDialog->selectOrMoveThisPoint(pickedPoint); moveSelectPoint = false; } else { if (registerPoint) { /*qDebug("Found point for add %i %i -> %f %f %f", currentMousePosition.x(), currentMousePosition.y(), pickedPoint[0], pickedPoint[1], pickedPoint[2]); */ //find the normal of the face we just clicked bool picked = Pick(currentMousePosition.x(), currentMousePosition.y(), pickedPoint); std::vector face; int result = GLPickTri::PickVisibleFace(currentMousePosition.x(), currentMousePosition.y(), mm.cm, face); if ((result == 0) || (face[0] == NULL)) { qDebug() << "find nearest face failed!"; } else { CFaceO::NormalType faceNormal = face[0]->N(); //qDebug() << "found face normal: " << faceNormal[0] << faceNormal[1] << faceNormal[2]; //if we didn't find a face then don't add the point because the user was probably //clicking on another mesh opened inside the glarea pickPointsDialog->addMoveSelectPoint(pickedPoint, faceNormal); } registerPoint = false; } } drawPickedPoints(pickPointsDialog->getPickedPointTreeWidgetItemVector(), mm.cm.bbox, painter); } bool EditPickPointsPlugin::StartEdit(MeshModel & mm, GLArea * gla, MLSceneGLSharedDataContext* /*cont*/) { //qDebug() << "StartEdit Pick Points: " << mm.fileName.c_str() << " ..." << mm.cm.fn; //if there are no faces then we can't do anything with this plugin if (mm.cm.fn < 1) { if (NULL != pickPointsDialog) { pickPointsDialog->hide(); } //show message QMessageBox::warning(gla->window(), "Edit Pick Points", "Sorry, this mesh has no faces on which picked points can sit.", QMessageBox::Ok, QMessageBox::Ok); return false; } //get the cursor QCursor *cursor = QApplication::overrideCursor(); if (cursor) overrideCursorShape = cursor->shape(); else overrideCursorShape = Qt::ArrowCursor; //set this so redraw can use it glArea = gla; //Create GUI window if we don't already have one if (pickPointsDialog == 0) { pickPointsDialog = new PickPointsDialog(this, gla->window()); } currentModel = &mm; //set the current mesh pickPointsDialog->setCurrentMeshModel(&mm, gla); //show the dialog pickPointsDialog->show(); return true; } void EditPickPointsPlugin::EndEdit(MeshModel & mm, GLArea * /*gla*/, MLSceneGLSharedDataContext* /*cont*/) { //qDebug() << "EndEdit Pick Points: " << mm.fileName.c_str() << " ..." << mm.cm.fn; // some cleaning at the end. if ((mm.cm.fn > 0) && (pickPointsDialog != NULL)) { //now that were are ending tell the dialog to save any points it has to metadata pickPointsDialog->savePointsToMetaData(); //remove the dialog from the screen pickPointsDialog->hide(); QApplication::setOverrideCursor(QCursor((Qt::CursorShape)overrideCursorShape)); this->glArea = 0; } } void EditPickPointsPlugin::mousePressEvent(QMouseEvent *event, MeshModel &mm, GLArea *gla) { //qDebug() << "mouse press Pick Points: " << mm.fileName.c_str() << " ..."; //if there are no faces then we can't do anything with this plugin if (mm.cm.fn < 1) return; if (Qt::RightButton == event->button() && pickPointsDialog->getMode() != PickPointsDialog::ADD_POINT) { currentMousePosition = QPoint(QT2VCG_X(gla, event), QT2VCG_Y(gla, event)); pickPointsDialog->recordNextPointForUndo(); //set flag that we need to add a new point moveSelectPoint = true; } } void EditPickPointsPlugin::mouseMoveEvent(QMouseEvent *event, MeshModel &mm, GLArea *gla) { //qDebug() << "mousemove pick Points: " << mm.fileName.c_str() << " ..."; //if there are no faces then we can't do anything with this plugin if (mm.cm.fn < 1) return; if (Qt::RightButton == event->button() && pickPointsDialog->getMode() != PickPointsDialog::ADD_POINT) { //qDebug() << "mouse move left button and move mode: "; currentMousePosition = QPoint(QT2VCG_X(gla, event), QT2VCG_Y(gla, event)); //event->pos(); //set flag that we need to add a new point registerPoint = true; } } void EditPickPointsPlugin::mouseReleaseEvent(QMouseEvent *event, MeshModel &mm, GLArea * gla) { //qDebug() << "mouseRelease Pick Points: " << mm.fileName.c_str() << " ..."; //if there are no faces then we can't do anything with this plugin if (mm.cm.fn < 1) return; //only add points for the left button if (Qt::RightButton == event->button()) { currentMousePosition = QPoint(QT2VCG_X(gla, event), QT2VCG_Y(gla, event));//event->pos(); //set flag that we need to add a new point registerPoint = true; } } void EditPickPointsPlugin::drawPickedPoints( std::vector &pointVector, Box3m &boundingBox, QPainter *painter) { assert(glArea); Point3m size = boundingBox.Dim(); //how we scale the object indicating the normal at each selected point Scalarm scaleFactor = (size[0] + size[1] + size[2]) / 90.0; //qDebug() << "scaleFactor: " << scaleFactor; glPushAttrib(GL_ALL_ATTRIB_BITS); // enable color tracking glEnable(GL_COLOR_MATERIAL); //draw the things that we always want to show, like the names glDepthFunc(GL_ALWAYS); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); //set point attributes glPointSize(4.5); bool showNormal = pickPointsDialog->showNormal(); bool showPin = pickPointsDialog->drawNormalAsPin(); for (int i = 0; i < pointVector.size(); ++i) { PickedPointTreeWidgetItem * item = pointVector[i]; //if the point has been set (it may not be if a template has been loaded) if (item->isActive()) { Point3m point = item->getPoint(); glColor(vcg::Color4b(vcg::Color4b::Blue)); glLabel::render(painter, point, QString(item->getName())); //draw the dot if we arnt showing the normal or showing the normal as a line if (!showNormal || !showPin) { if (item->isSelected()) glColor(vcg::Color4b(Color4b::Green)); glBegin(GL_POINTS); glVertex(point); glEnd(); } } } //now draw the things that we want drawn if they are not ocluded //we can see in bright red glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_MODELVIEW); Point3m yaxis(Scalarm(0), Scalarm(1), Scalarm(0)); for (int i = 0; i < pointVector.size(); ++i) { PickedPointTreeWidgetItem * item = pointVector[i]; //if the point has been set (it may not be if a template has been loaded) if (item->isActive()) { Point3m point = item->getPoint(); if (showNormal) { Point3m normal = item->getNormal(); if (showPin) { //dot product Scalarm angle = (Angle(normal, yaxis) * 180.0 / PI); //cross product Point3m axis = yaxis^normal; //qDebug() << "angle: " << angle << " x" << axis[0] << " y" << axis[1] << " z" << axis[2]; //bluegreen and a little clear glColor4f(0.0f, 1.0f, 0.0f, 0.7f); //glColor(Color4b::Green); glPushMatrix(); //move the pin to where it needs to be glTranslatef(point[0], point[1], point[2]); glRotatef(angle, axis[0], axis[1], axis[2]); glScalef(0.2*scaleFactor, 1.5*scaleFactor, 0.2*scaleFactor); glBegin(GL_TRIANGLES); //front glNormal3f(0, -1, 1); glVertex3f(0, 0, 0); glVertex3f(1, 1, 1); glVertex3f(-1, 1, 1); //right glNormal3f(1, -1, 0); glVertex3f(0, 0, 0); glVertex3f(1, 1, -1); glVertex3f(1, 1, 1); //left glNormal3f(-1, -1, 0); glVertex3f(0, 0, 0); glVertex3f(-1, 1, 1); glVertex3f(-1, 1, -1); //back glNormal3f(0, -1, -1); glVertex3f(0, 0, 0); glVertex3f(-1, 1, -1); glVertex3f(1, 1, -1); //top //if it is selected color it green if (item->isSelected()) glColor4f(0.0f, 0.0f, 1.0f, 0.7f); glNormal3f(0, 1, 0); glVertex3f(1, 1, 1); glVertex3f(1, 1, -1); glVertex3f(-1, 1, -1); glNormal3f(0, 1, 0); glVertex3f(1, 1, 1); glVertex3f(-1, 1, -1); glVertex3f(-1, 1, 1); //change back if (item->isSelected()) glColor4f(0.0f, 1.0f, 0.0f, 0.7f); glEnd(); glPopMatrix(); } else { glColor(vcg::Color4b(vcg::Color4b::Green)); glBegin(GL_LINES); glVertex(point); glVertex(point + (normal*scaleFactor)); glEnd(); } } glColor(vcg::Color4b(vcg::Color4b::Red)); //glArea->renderText(point[0], point[1], point[2], QString(item->getName()) ); } } glDisable(GL_BLEND); glDisable(GL_COLOR_MATERIAL); glDisable(GL_DEPTH_TEST); glPopAttrib(); }