mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-19 19:14:42 +00:00
388 lines
14 KiB
C++
388 lines
14 KiB
C++
/****************************************************************************
|
||
* MeshLab o o *
|
||
* A versatile mesh processing toolbox o o *
|
||
* _ O _ *
|
||
* Copyright(C) 2008 \/)\/ *
|
||
* 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. *
|
||
* *
|
||
****************************************************************************/
|
||
/****************************************************************************
|
||
History
|
||
$Log: editfit.cpp,v $
|
||
****************************************************************************/
|
||
#include "editfit.h"
|
||
|
||
using namespace vcg;
|
||
|
||
EditFitPlugin::EditFitPlugin():startGesture(false),pickMode(false)
|
||
{
|
||
toolBox=NULL;
|
||
showGesture3D=true;
|
||
}
|
||
|
||
const QString EditFitPlugin::Info()
|
||
{
|
||
return tr("Allow to fit some primitive.");
|
||
}
|
||
|
||
void EditFitPlugin::StartEdit(MeshModel &, GLArea * gla){
|
||
//Disabilito lo swap automatico del double buffering
|
||
//e lo gestisco io direttamente con gla->swapBuffers().
|
||
if(toolBox==NULL){
|
||
toolBox=new FitToolBox(gla->window());
|
||
QObject::connect(toolBox,SIGNAL(click_on_buttonCylinder()) ,this,SLOT(change_buttonCylinder()));
|
||
QObject::connect(toolBox,SIGNAL(click_on_buttonBox()) ,this,SLOT(change_buttonBox()));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxGesture3d(bool)),this,SLOT(change_checkBoxGesture3d(bool)));
|
||
toolBox->show();
|
||
}
|
||
//gla->setDoubleBufferSwap(false);
|
||
gla->setCursor(QCursor(QPixmap(":/images/cur_measure.png"),15,15));
|
||
gla->update();
|
||
glewInit();
|
||
}
|
||
void EditFitPlugin::EndEdit(MeshModel &, GLArea *){
|
||
if(toolBox!=NULL){
|
||
delete toolBox;
|
||
toolBox=NULL;
|
||
}
|
||
//Riabilito lo swap automatico del double buffering.
|
||
//gla->setDoubleBufferSwap(true);
|
||
gesture3D.clear();
|
||
gesture2D.clear();
|
||
listaPrimitive.clear();
|
||
}
|
||
|
||
void EditFitPlugin::mousePressEvent(QMouseEvent *ev, MeshModel &, GLArea *){
|
||
if(ev->button()==Qt::LeftButton){
|
||
startGesture=true;
|
||
vcg::Point2<int> tmp(ev->x(),ev->y());
|
||
gesture2D.push_back(tmp);
|
||
lastPoint=tmp;
|
||
gesture3D.clear();
|
||
listaPrimitive.clear();
|
||
}
|
||
}
|
||
void EditFitPlugin::mouseMoveEvent(QMouseEvent *ev, MeshModel &, GLArea * gla){
|
||
if(startGesture){
|
||
vcg::Point2<int> newPoint(ev->x(),ev->y());
|
||
LineRasterDDA(lastPoint.X(),lastPoint.Y(),newPoint.X(),newPoint.Y());
|
||
lastPoint=newPoint;
|
||
}
|
||
gla->update();
|
||
}
|
||
void EditFitPlugin::mouseReleaseEvent(QMouseEvent *ev, MeshModel &, GLArea * gla){
|
||
if(ev->button()==Qt::LeftButton){
|
||
startGesture=false;
|
||
pickMode=true;
|
||
}
|
||
//DrawInPickingMode(gla);
|
||
//ProcessPick(gla);
|
||
}
|
||
void EditFitPlugin::Decorate(MeshModel &, GLArea * gla){
|
||
if(pickMode){
|
||
DrawInPickingMode(gla);
|
||
//ProcessPick(gla);
|
||
pickMode=false;
|
||
|
||
if(gesture3D.size()!=0){
|
||
switch(selectedPrimitive){
|
||
|
||
case CYLINDER:
|
||
Cylinder *c;
|
||
c = new Cylinder(&gesture2D,&gesture3D,&gla->mm()->cm);
|
||
QObject::connect(c,SIGNAL(updateGlArea()),this,SLOT(slot_UpdateGlArea()));
|
||
QObject::connect(c,SIGNAL(updateDebugStapModeSize(int)),toolBox,SLOT(slot_InitspinBoxStepMode(int)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxCloudNearPoints(bool)),c,SLOT(change_checkBoxCloudNearPoints(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxLines(bool)), c,SLOT(change_checkBoxLines(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxSelectionMesh(bool)), c,SLOT(change_checkBoxSelectionMesh(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxCloudSampling(bool)), c,SLOT(change_checkBoxCloudSampling(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxObjectSpace(bool)), c,SLOT(change_checkBoxObjectSpace(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxStepMode(bool)), c,SLOT(change_checkBoxStepMode(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_spinBoxStepMode(int)), c,SLOT(change_spinBoxStepMode(int)));
|
||
listaPrimitive.push_back(c);
|
||
break;
|
||
|
||
case BOX:
|
||
Box *s;
|
||
s = new Box(&gesture2D,&gesture3D,&gla->mm()->cm);
|
||
QObject::connect(s,SIGNAL(updateGlArea()),this,SLOT(slot_UpdateGlArea()));
|
||
QObject::connect(s,SIGNAL(updateDebugStapModeSize(int)),toolBox,SLOT(slot_InitspinBoxStepMode(int)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxCloudNearPoints(bool)),s,SLOT(change_checkBoxCloudNearPoints(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxLines(bool)), s,SLOT(change_checkBoxLines(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxSelectionMesh(bool)), s,SLOT(change_checkBoxSelectionMesh(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxCloudSampling(bool)), s,SLOT(change_checkBoxCloudSampling(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxObjectSpace(bool)), s,SLOT(change_checkBoxObjectSpace(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_checkBoxStepMode(bool)), s,SLOT(change_checkBoxStepMode(bool)));
|
||
QObject::connect(toolBox,SIGNAL(click_on_spinBoxStepMode(int)), s,SLOT(change_spinBoxStepMode(int)));
|
||
listaPrimitive.push_back(s);
|
||
break;
|
||
}
|
||
std::vector<Primitive*>::iterator i;
|
||
for(i=listaPrimitive.begin();i<listaPrimitive.end();++i){
|
||
(*i)->start();
|
||
}
|
||
}
|
||
gesture2D.clear();
|
||
}else{
|
||
|
||
//DrawInPickingMode(gla);
|
||
DrawGesture2D(gla);
|
||
DrawGesture3D();
|
||
|
||
|
||
//Disegno le primitive:
|
||
std::vector<Primitive*>::iterator i;
|
||
for(i=listaPrimitive.begin();i<listaPrimitive.end();++i){
|
||
(*i)->Draw();
|
||
}
|
||
|
||
//gla->swapBuffers();
|
||
gla->update();
|
||
}
|
||
}
|
||
/*
|
||
void EditFitPlugin::DrawInPickingMode(GLArea * gla){
|
||
glDrawBuffer(GL_BACK);
|
||
//glDrawBuffer(GL_AUX1);
|
||
glClearColor(255,255,255,255);
|
||
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
|
||
glEnable(GL_DEPTH_TEST);
|
||
glDisable(GL_DITHER);
|
||
glEnable(GL_CULL_FACE);
|
||
glDisable(GL_LIGHTING);
|
||
|
||
//glewInit();
|
||
static GLfloat linear[3] = {0.0,0.0,0.001};
|
||
static GLfloat cost[3] = {1.0,0.0,0.0};
|
||
glPointParameterf(GL_POINT_SIZE_MIN, -100.0);
|
||
glPointParameterf(GL_POINT_SIZE_MAX, 100.0);
|
||
|
||
for(unsigned int i=0;i<gla->mm()->glw.m->vert.size();i++){
|
||
glColor4ubv((const GLubyte *)&i);
|
||
glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, linear);
|
||
glPointSize(1);
|
||
glBegin(GL_POINTS);
|
||
glVertex(gla->mm()->glw.m->vert[i].P());
|
||
glEnd();
|
||
}
|
||
glEnable(GL_DITHER);
|
||
glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, cost);
|
||
glPointSize(1);
|
||
glDrawBuffer(GL_BACK);
|
||
/*Disegno ogni punto con un colore diverso partendo da RGBA==(0,0,0,0)
|
||
fino al massimo RGBA==(255,255,255,254) perch<63> (255,255,255,255) <20>
|
||
lo sfondo.Quindi al massimo posso distingure 4294967295 punti*
|
||
}
|
||
*/
|
||
|
||
void EditFitPlugin::DrawInPickingMode(GLArea * gla){
|
||
|
||
/*Disegno ogni punto con un colore diverso partendo da RGBA==(0,0,0,0)
|
||
fino al massimo RGBA==(255,255,255,254) perch<63> (255,255,255,255) <20>
|
||
lo sfondo.Quindi al massimo posso distingure 4294967295 punti*/
|
||
|
||
QGLFramebufferObject framebuffer(gla->width(),gla->height(),QGLFramebufferObject::Depth,GL_TEXTURE_RECTANGLE_EXT);
|
||
if(!framebuffer.isValid())QMessageBox::critical(gla,"Error","Invalid frame buffer");;
|
||
if(!framebuffer.bind()) QMessageBox::critical(gla,"Error","Error binding the frame buffer");
|
||
//framebuffer.setAutoBufferSwap(false);
|
||
glClearColor(1,1,1,1);
|
||
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
|
||
glEnable(GL_DEPTH_TEST);
|
||
glDisable(GL_DITHER);
|
||
glDisable(GL_TEXTURE_2D);
|
||
glEnable(GL_CULL_FACE);
|
||
glDisable(GL_LIGHTING);
|
||
|
||
glewInit();
|
||
static GLfloat linear[3] = {0.0,0.0,0.001};
|
||
static GLfloat cost[3] = {1.0,0.0,0.0};
|
||
glPointParameterf(GL_POINT_SIZE_MIN, -100.0);
|
||
glPointParameterf(GL_POINT_SIZE_MAX, 100.0);
|
||
|
||
for(unsigned int i=0;i<gla->mm()->glw.m->vert.size();i++){
|
||
glColor4ubv((const GLubyte *)&i);
|
||
glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, linear);
|
||
glPointSize(1);
|
||
glBegin(GL_POINTS);
|
||
glVertex(gla->mm()->glw.m->vert[i].P());
|
||
glEnd();
|
||
}
|
||
glEnable(GL_DITHER);
|
||
glEnable(GL_TEXTURE_2D);
|
||
glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, cost);
|
||
glPointSize(1);
|
||
QImage img=framebuffer.toImage();
|
||
//img.save("debug.bmp");
|
||
if(img.isNull())QMessageBox::critical(gla,"Error","Error by building the image frame buffer");
|
||
ProcessPick(img,gla);
|
||
framebuffer.release();
|
||
}
|
||
void EditFitPlugin::ProcessPick (const QImage &img,GLArea * gla){
|
||
|
||
unsigned int z;
|
||
//Visto che in drawInPickingMode disegno pixel grossi 5, inserirei sempre lo stesso punto3D
|
||
//perch<63> per piu pixel ha sempre lo stesso colore, per questo uso last.
|
||
unsigned int last=std::numeric_limits<unsigned int>::max(); //sarebbe 4294967295;
|
||
for(int i=0;i<(int)gesture2D.size();i++){
|
||
QRgb k=img.pixel(gesture2D[i].X(),gesture2D[i].Y());
|
||
int red =qRed(k);
|
||
int green=qGreen(k);
|
||
int blue =qBlue(k);
|
||
int alpha=qAlpha(k);
|
||
z=qRgba(blue,green,red,alpha);
|
||
/*
|
||
//Bedin_Debug:
|
||
char c[100];
|
||
std::string r;
|
||
sprintf(c,"\n%d\n",z);
|
||
r.append("r"+std::bitset<32>(red).to_string()+"\n");
|
||
r.append("g"+std::bitset<32>(green).to_string()+"\n");
|
||
r.append("b"+std::bitset<32>(blue).to_string()+"\n");
|
||
r.append("a"+std::bitset<32>(alpha).to_string()+"\n");
|
||
r.append(c);
|
||
r.append("X"+std::bitset<32>(z).to_string()+"\n");
|
||
QMessageBox::information(0,"Messaggio:",r.c_str());
|
||
//End_Debug
|
||
*/
|
||
if(z!=std::numeric_limits<unsigned int>::max() && z!=last){
|
||
gesture3D.push_back(vcg::Point3f(gla->mm()->glw.m->vert[z].P()));
|
||
last=z;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
void EditFitPlugin::ProcessPick (GLArea * gla){
|
||
unsigned int k=0;
|
||
//Visto che in drawInPickingMode disegno pixel grossi 5, inserirei sempre lo stesso punto3D
|
||
//perch<63> per piu pixel ha sempre lo stesso colore, per questo uso last.
|
||
unsigned int last=std::numeric_limits<unsigned int>::max(); //sarebbe 4294967295;
|
||
glReadBuffer(GL_BACK);
|
||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||
|
||
/*
|
||
//Debug:
|
||
//unsigned char *data=(unsigned char *)malloc(4*gla->width()*gla->height()*sizeof(unsigned char));
|
||
//glReadPixels(0,0,gla->width(),gla->height(),GL_RGBA,GL_UNSIGNED_BYTE,data);
|
||
//QImage pippo(data,gla->width(),gla->height(),QImage::Format_ARGB32);
|
||
//pippo.save("debug.bmp");
|
||
//fine Debug.
|
||
|
||
|
||
for(int i=0;i<(int)gesture2D.size();i++){
|
||
glReadPixels(gesture2D[i].X(),(gla->height()-1)-gesture2D[i].Y(),1,1,GL_RGBA,GL_UNSIGNED_BYTE,&k);
|
||
if(k!=std::numeric_limits<unsigned int>::max() && k!=last){
|
||
gesture3D.push_back(vcg::Point3f(gla->mm()->glw.m->vert[k].P()));
|
||
last=k;
|
||
}
|
||
}
|
||
}
|
||
*/
|
||
void EditFitPlugin::DrawGesture2D (GLArea * gla){
|
||
//2d mode
|
||
glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_LINE_BIT|GL_POINT_BIT|GL_CURRENT_BIT|GL_LIGHTING_BIT|GL_COLOR_BUFFER_BIT);
|
||
glDisable(GL_LIGHTING);
|
||
glDisable(GL_TEXTURE_2D);
|
||
glDisable(GL_DEPTH_TEST);
|
||
glDisable(GL_COLOR_MATERIAL);
|
||
glDisable(GL_BLEND);
|
||
glDepthMask(false);
|
||
glPointSize(2.0);
|
||
glColor3f(0,0,1.0);
|
||
glMatrixMode(GL_PROJECTION);
|
||
glPushMatrix();
|
||
glLoadIdentity();
|
||
gluOrtho2D(0,gla->width(),gla->height(),0);
|
||
glMatrixMode(GL_MODELVIEW);
|
||
glPushMatrix();
|
||
glLoadIdentity();
|
||
//////////////////////////////////////////
|
||
std::vector<vcg::Point2i>::iterator i;
|
||
for(i=gesture2D.begin();i<gesture2D.end();++i){
|
||
glBegin(GL_POINTS);
|
||
glVertex2i(i->X(),i->Y());
|
||
glEnd();
|
||
}
|
||
//Out 2d mode
|
||
glEnable(GL_DEPTH_TEST);
|
||
glMatrixMode(GL_PROJECTION);
|
||
glPopMatrix();
|
||
glMatrixMode(GL_MODELVIEW);
|
||
glPopMatrix();
|
||
glPopAttrib();
|
||
}
|
||
|
||
|
||
void EditFitPlugin::DrawGesture3D(){
|
||
if(showGesture3D){
|
||
glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_LINE_BIT|GL_POINT_BIT|GL_CURRENT_BIT|GL_LIGHTING_BIT|GL_COLOR_BUFFER_BIT);
|
||
glDisable(GL_LIGHTING);
|
||
glDisable(GL_TEXTURE_2D);
|
||
glDisable(GL_DEPTH_TEST);
|
||
glDisable(GL_COLOR_MATERIAL);
|
||
glDisable(GL_BLEND);
|
||
|
||
std::vector<vcg::Point3f>::iterator i;
|
||
for(i=gesture3D.begin();i<gesture3D.end();++i){
|
||
glColor3f(0,1.0,0);
|
||
glPointSize(3);
|
||
glBegin(GL_POINTS);
|
||
glVertex(*i);
|
||
glEnd();
|
||
}
|
||
glPointSize(1);
|
||
glPopAttrib();
|
||
}
|
||
}
|
||
void EditFitPlugin::LineRasterDDA (float x1,float y1,float x2,float y2){
|
||
float x=x1,y=y1,m;
|
||
float dx=x2-x1;
|
||
float dy=y2-y1;
|
||
if(abs(dx)>=abs(dy)){
|
||
m=abs(dx);
|
||
}else{
|
||
m=abs(dy);
|
||
}
|
||
for(int i=1;i<=m;i++){
|
||
x=x+dx/m;
|
||
y=y+dy/m;
|
||
gesture2D.push_back(vcg::Point2<int>((int)x,(int)y));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
EditFitPlugin::~EditFitPlugin(){
|
||
actionList.clear();
|
||
listaPrimitive.clear();
|
||
}
|
||
//Slots:
|
||
void EditFitPlugin::change_buttonCylinder(){
|
||
selectedPrimitive=CYLINDER;
|
||
}
|
||
void EditFitPlugin::change_buttonBox(){
|
||
//QMessageBox::information(0,"Box","Box");
|
||
selectedPrimitive=BOX;
|
||
}
|
||
void EditFitPlugin::change_checkBoxGesture3d(bool b){
|
||
showGesture3D=b;
|
||
}
|
||
void EditFitPlugin::slot_UpdateGlArea(){
|
||
//gla->update();
|
||
}
|