mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-13 08:09:39 +00:00
424 lines
12 KiB
C++
424 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 <GL/glew.h>
|
|
#include <qdebug.h>
|
|
|
|
#include "editpickpoints.h"
|
|
#include <meshlab/glarea.h>
|
|
|
|
#include <wrap/gl/picking.h>
|
|
#include <wrap/gl/pick.h>
|
|
#include <wrap/qt/gl_label.h>
|
|
#include <wrap/qt/trackball.h>
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
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<Point3m>(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<Point3m>(currentMousePosition.x(), currentMousePosition.y(), pickedPoint);
|
|
std::vector<CFaceO*> face;
|
|
int result = GLPickTri<CMeshO>::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<PickedPointTreeWidgetItem*> &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();
|
|
|
|
}
|