Guido Ranzuglia granzuglia 2c8bb1bbf0 added GPL incipit
2009-05-18 14:41:13 +00:00

436 lines
12 KiB
C++

/****************************************************************************
* 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 <QtGui>
#include <GL/glew.h>
#include "editpickpoints.h"
#include <meshlab/mainwindow.h>
#include <wrap/gl/picking.h>
#include <wrap/gl/pick.h>
#include <math.h>
using namespace vcg;
#define PI 3.14159265
EditPickPointsPlugin::EditPickPointsPlugin()
{
//initialize to false so we dont end up collection 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");
}
//called
void EditPickPointsPlugin::Decorate(MeshModel &mm, GLArea *gla)
{
//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
Point3f pickedPoint;
if (moveSelectPoint && Pick<Point3f>(currentMousePosition.x(),gla->height()-currentMousePosition.y(),pickedPoint)){
/* 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 incase it wants the information
pickPointsDialog->selectOrMoveThisPoint(pickedPoint);
moveSelectPoint = false;
} else if(registerPoint && Pick<Point3f>(currentMousePosition.x(),gla->height()-currentMousePosition.y(),pickedPoint))
{
/* 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
CFaceO *face;
bool result = GLPickTri<CMeshO>::PickNearestFace(currentMousePosition.x(),gla->height()-currentMousePosition.y(),
mm.cm, face);
if(!result){
qDebug() << "find nearest face failed!";
} else
{
CFaceO::NormalType faceNormal = face->N();
//qDebug() << "found face normal: " << faceNormal[0] << faceNormal[1] << faceNormal[2];
//if we didnt find a face then dont 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);
}
void EditPickPointsPlugin::StartEdit(MeshModel &mm, GLArea *gla )
{
//qDebug() << "StartEdit Pick Points: " << mm.fileName.c_str() << " ..." << mm.cm.fn;
//if there are no faces then we cant 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;
}
//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 dont 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();
}
void EditPickPointsPlugin::EndEdit(MeshModel &mm, GLArea *gla)
{
//qDebug() << "EndEdit Pick Points: " << mm.fileName.c_str() << " ..." << mm.cm.fn;
// some cleaning at the end.
if(mm.cm.fn > 0)
{
assert(pickPointsDialog);
//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) );
}
}
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 cant do anything with this plugin
if(mm.cm.fn < 1) return;
if(Qt::LeftButton | event->buttons())
{
gla->suspendedEditor = true;
QCoreApplication::sendEvent(gla, event);
gla->suspendedEditor = false;
}
if(Qt::RightButton == event->button() &&
pickPointsDialog->getMode() != PickPointsDialog::ADD_POINT){
currentMousePosition = event->pos();
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 cant do anything with this plugin
if(mm.cm.fn < 1) return;
if(Qt::LeftButton | event->buttons())
{
gla->suspendedEditor = true;
QCoreApplication::sendEvent(gla, event);
gla->suspendedEditor = false;
}
if(Qt::RightButton & event->buttons() &&
pickPointsDialog->getMode() != PickPointsDialog::ADD_POINT){
//qDebug() << "mouse move left button and move mode: ";
currentMousePosition = 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 cant do anything with this plugin
if(mm.cm.fn < 1) return;
if(Qt::LeftButton | event->buttons())
{
gla->suspendedEditor = true;
QCoreApplication::sendEvent(gla, event);
gla->suspendedEditor = false;
}
//only add points for the left button
if(Qt::RightButton == event->button()){
currentMousePosition = event->pos();
//set flag that we need to add a new point
registerPoint = true;
}
}
void EditPickPointsPlugin::drawPickedPoints(
std::vector<PickedPointTreeWidgetItem*> &pointVector, vcg::Box3f &boundingBox)
{
assert(glArea);
vcg::Point3f size = boundingBox.Dim();
//how we scale the object indicating the normal at each selected point
float 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()){
Point3f point = item->getPoint();
glColor(Color4b::Blue);
glArea->renderText(point[0], point[1], point[2], 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(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);
Point3f yaxis;
yaxis[0] = 0;
yaxis[1] = 1;
yaxis[2] = 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()){
Point3f point = item->getPoint();
if(showNormal)
{
Point3f normal = item->getNormal();
if(showPin)
{
//dot product
float angle = (Angle(normal,yaxis) * 180.0 / PI);
//cross product
Point3f 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(Color4b::Green);
glBegin(GL_LINES);
glVertex(point);
glVertex(point+(normal*scaleFactor));
glEnd();
}
}
glColor(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();
}