mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-13 08:09:39 +00:00
882 lines
24 KiB
C++
882 lines
24 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$
|
|
Revision 1.5 2008/02/27 14:50:24 benedetti
|
|
fixed on_freehand_mesh_dragging, minor cleanups, now all functionality works
|
|
|
|
Revision 1.4 2008/02/26 21:35:17 benedetti
|
|
corrected after quaternion/similarity/trackball changes, on_freehand_mesh_dragging still doesn't work
|
|
|
|
Revision 1.3 2008/02/22 20:24:42 benedetti
|
|
refactored, cleaned up a bit, few feats added
|
|
|
|
Revision 1.2 2008/02/17 20:57:33 benedetti
|
|
updated following new specs (still got to clean up)
|
|
|
|
Revision 1.1 2008/02/16 14:29:35 benedetti
|
|
first version
|
|
|
|
|
|
****************************************************************************/
|
|
#include <QtGui>
|
|
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <meshlab/glarea.h>
|
|
|
|
#include <vcg/complex/algorithms/update/position.h>
|
|
#include <vcg/complex/algorithms/update/bounding.h>
|
|
#include <vcg/complex/algorithms/update/selection.h>
|
|
#include <vcg/space/fitting3.h>
|
|
|
|
#include <wrap/qt/trackball.h>
|
|
|
|
#include "editstraightener.h"
|
|
|
|
using namespace vcg;
|
|
|
|
EditStraightener::EditStraightener()
|
|
:dialog(NULL),dialog_dock(NULL),
|
|
gla(NULL),mm(NULL),refsize(0),currentmode(ES_Normal),
|
|
origin(NULL),old_origin(NULL),dragged_origin(NULL),
|
|
dragged_mesh(NULL),drawned_axes(NULL),undosystem(NULL),draw_bbox(true)
|
|
{}
|
|
|
|
const QString EditStraightener::Info()
|
|
{
|
|
return tr("Change the coordinate frame of a mesh.");
|
|
}
|
|
|
|
bool EditStraightener::StartEdit(MeshModel &m, GLArea *g )
|
|
{
|
|
//cleanup:
|
|
gla=NULL;
|
|
mm=NULL;
|
|
EndEdit(m,g);
|
|
gla = g;
|
|
mm = &m;
|
|
assert( (gla!=NULL) && (mm != NULL));
|
|
|
|
gla->setCursor(QCursor(QPixmap(":/images/cur_straightener.png"),15,15));
|
|
|
|
refsize=mm->cm.bbox.Diag()/2.0;
|
|
|
|
assert(origin==NULL);
|
|
origin=new MovableCoordinateFrame(refsize);
|
|
origin->basecolor=Color4b(170,170,0,255);
|
|
origin->xcolor=Color4b(170,0,0,255);
|
|
origin->ycolor=Color4b(0,170,0,255);
|
|
origin->zcolor=Color4b(0,0,170,255);
|
|
origin->linewidth=1.5;
|
|
|
|
currentmode=ES_Normal;
|
|
|
|
assert(dialog==NULL);
|
|
dialog = new EditStraightenerDialog(gla->window());
|
|
dialog_dock = new QDockWidget(gla->window());
|
|
dialog_dock->setAllowedAreas(Qt::NoDockWidgetArea);
|
|
dialog_dock->setWidget(dialog);
|
|
QPoint p = gla->window()->mapToGlobal(QPoint(0,0));
|
|
int x = -5 + p.x() + gla->window()->width() - dialog->width();
|
|
int y = p.y();
|
|
int w = dialog->width();
|
|
int h = dialog->height();
|
|
dialog_dock->setGeometry(x,y,w,h);
|
|
dialog_dock->setFloating(true);
|
|
connect(dialog, SIGNAL( begin_action() ),
|
|
this, SLOT( on_begin_action() ) );
|
|
connect(dialog, SIGNAL( apply() ),
|
|
this, SLOT( on_apply() ) );
|
|
connect(dialog, SIGNAL( freeze() ),
|
|
this, SLOT( on_freeze() ) );
|
|
connect(dialog, SIGNAL( undo() ),
|
|
this, SLOT( on_undo() ) );
|
|
connect(dialog, SIGNAL( rot(float,Point3f) ),
|
|
this, SLOT( on_rot(float,Point3f) ) );
|
|
connect(dialog, SIGNAL( align_with_view() ),
|
|
this, SLOT( on_align_with_view() ) );
|
|
connect(dialog, SIGNAL( move_axis_to_bbox(int,float) ),
|
|
this, SLOT( on_move_axis_to_bbox(int,float) ) );
|
|
connect(dialog, SIGNAL( center_on_trackball() ),
|
|
this, SLOT( on_center_on_trackball() ) );
|
|
connect(dialog, SIGNAL( draw_on_mesh(bool,char,char) ),
|
|
this, SLOT( on_draw_on_mesh(bool,char,char) ) );
|
|
connect(dialog, SIGNAL( freehand_axis_dragging(bool) ),
|
|
this, SLOT( on_freehand_axis_dragging(bool) ) );
|
|
connect(dialog, SIGNAL( set_snap(float) ),
|
|
this, SLOT( on_set_snap(float) ) );
|
|
connect(dialog, SIGNAL( freehand_mesh_dragging(bool) ),
|
|
this, SLOT( on_freehand_mesh_dragging(bool) ) );
|
|
connect(dialog, SIGNAL( get_plane_from_selection(char,char) ),
|
|
this, SLOT( on_get_plane_from_selection(char,char) ) );
|
|
connect(dialog, SIGNAL( update_show(bool,bool,bool,bool,bool,bool,bool,bool,bool) ),
|
|
this, SLOT( on_update_show(bool,bool,bool,bool,bool,bool,bool,bool,bool) ) );
|
|
|
|
dialog->shoutShow();
|
|
dialog->SetFreeze(freezable());
|
|
|
|
dialog_dock->setVisible(true);
|
|
dialog_dock->layout()->update();
|
|
|
|
assert(undosystem==NULL);
|
|
undosystem=new UndoSystem(this);
|
|
|
|
gla->update();
|
|
assert(origin!=NULL);
|
|
return true;
|
|
}
|
|
|
|
void EditStraightener::EndEdit(MeshModel &, GLArea *)
|
|
{
|
|
if (dialog!=NULL) { delete dialog; dialog=NULL; }
|
|
if (dialog_dock!=NULL) { delete dialog_dock; dialog_dock=NULL; }
|
|
if (origin!=NULL) { delete origin; origin=NULL; }
|
|
if (old_origin!=NULL) { delete old_origin; old_origin=NULL; }
|
|
if (dragged_origin!=NULL) { delete dragged_origin; dragged_origin=NULL; }
|
|
if (dragged_mesh!=NULL) { delete dragged_mesh; dragged_mesh=NULL; }
|
|
if (drawned_axes!=NULL) { delete drawned_axes; drawned_axes=NULL; }
|
|
if (undosystem!=NULL) { delete undosystem; undosystem=NULL; }
|
|
|
|
if(gla!=NULL){
|
|
gla->releaseKeyboard();
|
|
gla->update();
|
|
}
|
|
gla=NULL;
|
|
mm=NULL;
|
|
}
|
|
|
|
void EditStraightener::Decorate(MeshModel &, GLArea *)
|
|
{
|
|
dialog->updateSfn(mm->cm.sfn);
|
|
|
|
if (currentmode == ES_FreehandAxisDragging){
|
|
old_origin->Render(gla);
|
|
dragged_origin->Render(gla);
|
|
} else {
|
|
origin->Render(gla);
|
|
}
|
|
|
|
if(currentmode == ES_FreehandMeshDragging)
|
|
dragged_mesh->Render();
|
|
|
|
if( (currentmode == ES_DrawOnMesh) && (drawned_axes!=NULL) ){
|
|
drawned_axes->Render(gla);
|
|
if (drawned_axes->IsReady()){
|
|
Point3f a1,a2,b1,b2;
|
|
drawned_axes->GetAxes(a1,a2,b1,b2);
|
|
origin->AlignWith(a2-a1,b2-b1,drawned_axes->firstchar,drawned_axes->secondchar);
|
|
on_apply();
|
|
delete drawned_axes;
|
|
drawned_axes=NULL;
|
|
currentmode=ES_Normal;
|
|
dialog->endSpecialMode();
|
|
gla->trackball.Reset();
|
|
gla->update();
|
|
}
|
|
}
|
|
|
|
if(draw_bbox){
|
|
Box3f bbox = mm->cm.trBB();
|
|
float mx=bbox.min[0],my=bbox.min[1],mz=bbox.min[2];
|
|
float Mx=bbox.max[0],My=bbox.max[1],Mz=bbox.max[2];
|
|
float x=math::Clamp(.0f,mx,Mx);
|
|
float y=math::Clamp(.0f,my,My);
|
|
float z=math::Clamp(.0f,mz,Mz);
|
|
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glEnable(GL_LINE_SMOOTH);
|
|
glEnable(GL_POINT_SMOOTH);
|
|
glLineWidth(2);
|
|
glPointSize(5);
|
|
glBegin(GL_LINES);
|
|
if(mx<0){ // negative x
|
|
glColor3f(.3f,.0f,.0f);
|
|
glVertex3f(mx,my,mz); glVertex3f(x,my,mz);
|
|
glVertex3f(mx,my,Mz); glVertex3f(x,my,Mz);
|
|
glVertex3f(mx,My,mz); glVertex3f(x,My,mz);
|
|
glVertex3f(mx,My,Mz); glVertex3f(x,My,Mz);
|
|
}
|
|
if(Mx>0){ // positive x
|
|
glColor3f(.6f,.3f,.3f);
|
|
glVertex3f(x,my,mz); glVertex3f(Mx,my,mz);
|
|
glVertex3f(x,my,Mz); glVertex3f(Mx,my,Mz);
|
|
glVertex3f(x,My,mz); glVertex3f(Mx,My,mz);
|
|
glVertex3f(x,My,Mz); glVertex3f(Mx,My,Mz);
|
|
}
|
|
if(my<0){ // negative y
|
|
glColor3f(.0f,.3f,.0f);
|
|
glVertex3f(mx,my,mz); glVertex3f(mx,y,mz);
|
|
glVertex3f(mx,my,Mz); glVertex3f(mx,y,Mz);
|
|
glVertex3f(Mx,my,mz); glVertex3f(Mx,y,mz);
|
|
glVertex3f(Mx,my,Mz); glVertex3f(Mx,y,Mz);
|
|
}
|
|
if(My>0) { // positive y
|
|
glColor3f(.3f,.6f,.3f);
|
|
glVertex3f(mx,y,mz); glVertex3f(mx,My,mz);
|
|
glVertex3f(mx,y,Mz); glVertex3f(mx,My,Mz);
|
|
glVertex3f(Mx,y,mz); glVertex3f(Mx,My,mz);
|
|
glVertex3f(Mx,y,Mz); glVertex3f(Mx,My,Mz);
|
|
}
|
|
if(mz<0) { // negative z
|
|
glColor3f(.0f,.0f,.3f);
|
|
glVertex3f(mx,my,mz); glVertex3f(mx,my,z);
|
|
glVertex3f(mx,My,mz); glVertex3f(mx,My,z);
|
|
glVertex3f(Mx,my,mz); glVertex3f(Mx,my,z);
|
|
glVertex3f(Mx,My,mz); glVertex3f(Mx,My,z);
|
|
}
|
|
if(Mz>0) { // positive z
|
|
glColor3f(.3f,.3f,.6f);
|
|
glVertex3f(mx,my,z); glVertex3f(mx,my,Mz);
|
|
glVertex3f(mx,My,z); glVertex3f(mx,My,Mz);
|
|
glVertex3f(Mx,my,z); glVertex3f(Mx,my,Mz);
|
|
glVertex3f(Mx,My,z); glVertex3f(Mx,My,Mz);
|
|
}
|
|
glEnd();
|
|
glBegin(GL_POINTS);
|
|
if((mx<0)&&(Mx>0)){ // x crosses 0
|
|
glColor3f(1.0f,.6f,.6f);
|
|
glVertex3f(x,my,mz);
|
|
glVertex3f(x,my,Mz);
|
|
glVertex3f(x,My,mz);
|
|
glVertex3f(x,My,Mz);
|
|
}
|
|
if((my<0)&&(My>0)){ // y crosses 0
|
|
glColor3f(.6f,1.0f,.6f);
|
|
glVertex3f(mx,y,mz);
|
|
glVertex3f(mx,y,Mz);
|
|
glVertex3f(Mx,y,mz);
|
|
glVertex3f(Mx,y,Mz);
|
|
}
|
|
if((mz<0)&&(Mz>0)){ // z crosses 0
|
|
glColor3f(.6f,.6f,1.0f);
|
|
glVertex3f(mx,my,z);
|
|
glVertex3f(mx,My,z);
|
|
glVertex3f(Mx,my,z);
|
|
glVertex3f(Mx,My,z);
|
|
}
|
|
glEnd();
|
|
glPopAttrib();
|
|
}
|
|
|
|
assert(!glGetError());
|
|
}
|
|
|
|
void EditStraightener::mousePressEvent(QMouseEvent *e, MeshModel &, GLArea * )
|
|
{
|
|
switch (currentmode) {
|
|
case ES_FreehandAxisDragging:
|
|
dragged_origin->MouseDown(e->x(), gla->height() - e->y(), QT2VCG(e->button(), e->modifiers()));
|
|
break;
|
|
case ES_FreehandMeshDragging:
|
|
dragged_mesh->MouseDown(e->x(), gla->height() - e->y(), QT2VCG(e->button(), e->modifiers()));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::mouseMoveEvent(QMouseEvent *e, MeshModel &, GLArea * )
|
|
{
|
|
switch (currentmode) {
|
|
case ES_FreehandAxisDragging:
|
|
dragged_origin->MouseMove(e->x (),gla->height () - e->y ());
|
|
break;
|
|
case ES_DrawOnMesh:
|
|
drawned_axes->mouseMove(e->pos());
|
|
break;
|
|
case ES_FreehandMeshDragging:
|
|
dragged_mesh->MouseMove(e->x (),gla->height () - e->y ());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::mouseReleaseEvent(QMouseEvent *e, MeshModel &, GLArea *)
|
|
{
|
|
switch (currentmode) {
|
|
case ES_FreehandAxisDragging:
|
|
dragged_origin->MouseUp(e->x (),gla->height () - e->y (), QT2VCG (e->button (), 0));
|
|
break;
|
|
case ES_DrawOnMesh:
|
|
drawned_axes->mouseRelease(e->pos());
|
|
break;
|
|
case ES_FreehandMeshDragging:
|
|
dragged_mesh->MouseUp(e->x (),gla->height () - e->y (), QT2VCG (e->button (), e->modifiers ()));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::keyReleaseEvent (QKeyEvent * e, MeshModel &, GLArea *)
|
|
{
|
|
int button = 0;
|
|
if (e->key () == Qt::Key_Control){
|
|
button = QT2VCG (Qt::NoButton, Qt::ControlModifier);
|
|
} else if (e->key () == Qt::Key_Shift) {
|
|
button = QT2VCG (Qt::NoButton, Qt::ShiftModifier);
|
|
} else if (e->key () == Qt::Key_Alt) {
|
|
button = QT2VCG (Qt::NoButton, Qt::AltModifier);
|
|
} else {
|
|
e->ignore();
|
|
gla->update();
|
|
return;
|
|
}
|
|
switch (currentmode) {
|
|
case ES_FreehandAxisDragging:
|
|
dragged_origin->ButtonUp(button);
|
|
break;
|
|
case ES_FreehandMeshDragging:
|
|
dragged_mesh->ButtonUp(button);
|
|
default:
|
|
e->ignore();
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
|
|
void EditStraightener::keyPressEvent (QKeyEvent * e, MeshModel &, GLArea *)
|
|
{
|
|
int button;
|
|
if (e->key () == Qt::Key_Control){
|
|
button = QT2VCG (Qt::NoButton, Qt::ControlModifier);
|
|
} else if (e->key () == Qt::Key_Shift) {
|
|
button = QT2VCG (Qt::NoButton, Qt::ShiftModifier);
|
|
} else if (e->key () == Qt::Key_Alt) {
|
|
button = QT2VCG (Qt::NoButton, Qt::AltModifier);
|
|
} else {
|
|
e->ignore();
|
|
gla->update();
|
|
return;
|
|
}
|
|
switch (currentmode) {
|
|
case ES_FreehandAxisDragging:
|
|
dragged_origin->ButtonDown(button);
|
|
break;
|
|
case ES_FreehandMeshDragging:
|
|
dragged_mesh->ButtonDown(button);
|
|
default:
|
|
e->ignore();
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
bool EditStraightener::freezable()
|
|
{
|
|
const float EPSILON=1e-4;
|
|
for(int i=0;i<4;i++)
|
|
for(int j=0;j<4;j++)
|
|
if( math::Abs(mm->cm.Tr[i][j] - (i==j?1:0)) > EPSILON)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// slots:
|
|
void EditStraightener::on_begin_action()
|
|
{
|
|
assert(origin->GetPosition()==Point3f(0,0,0));
|
|
assert(origin->GetRotation()==Quaternionf(0,Point3f(1,0,0)));
|
|
undosystem->BeginAction();
|
|
}
|
|
|
|
void EditStraightener::on_apply()
|
|
{
|
|
Matrix44f tr;
|
|
origin->GetTransform(tr);
|
|
origin->Reset(true,true);
|
|
undosystem->SaveTR();
|
|
mm->cm.Tr = Inverse(tr) * mm->cm.Tr ;
|
|
dialog->SetFreeze(freezable());
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_freeze()
|
|
{
|
|
assert(origin->GetPosition()==Point3f(0,0,0));
|
|
assert(origin->GetRotation()==Quaternionf(0,Point3f(1,0,0)));
|
|
on_begin_action();
|
|
gla->setWindowModified(true);
|
|
undosystem->SaveFreeze();
|
|
tri::UpdatePosition<CMeshO>::Matrix(mm->cm, mm->cm.Tr);
|
|
tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(mm->cm);
|
|
tri::UpdateBounding<CMeshO>::Box(mm->cm);
|
|
undosystem->SaveTR();
|
|
mm->cm.Tr.SetIdentity();
|
|
dialog->SetFreeze(false);
|
|
gla->trackball.Reset();
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_undo()
|
|
{
|
|
assert(undosystem->CanUndo());
|
|
undosystem->Undo();
|
|
dialog->SetFreeze(freezable());
|
|
gla->update();
|
|
}
|
|
|
|
|
|
void EditStraightener::on_rot(float angle_deg,Point3f axis)
|
|
{
|
|
on_begin_action();
|
|
origin->Rot(angle_deg,axis);
|
|
on_apply();
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_align_with_view()
|
|
{
|
|
on_begin_action();
|
|
origin->SetRotation(gla->trackball.track.rot);
|
|
on_apply();
|
|
gla->trackball.Reset();
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_move_axis_to_bbox(int axis, float value)
|
|
{
|
|
Box3f bbox = mm->cm.trBB();
|
|
Point3f p = origin->GetPosition();
|
|
p[axis]=bbox.min[axis] + (bbox.max[axis]-bbox.min[axis]) * value;
|
|
origin->SetPosition(p); // della parte begin_action\apply si occupa EditStraightenerDialog
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_center_on_trackball()
|
|
{
|
|
Box3f bbox;
|
|
foreach(MeshModel * m, gla->meshDoc.meshList)
|
|
bbox.Add(m->cm.trBB());
|
|
on_begin_action();
|
|
origin->SetPosition(bbox.Center()-(gla->trackball.track.tra) * (0.5*bbox.Diag()));
|
|
on_apply();
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_draw_on_mesh(bool begin,char c1,char c2)
|
|
{
|
|
if(begin){
|
|
assert(currentmode==ES_Normal);
|
|
on_begin_action();
|
|
drawned_axes = new DrawAxes(c1,c2);
|
|
currentmode=ES_DrawOnMesh;
|
|
} else {
|
|
assert(currentmode==ES_DrawOnMesh);
|
|
delete drawned_axes;
|
|
drawned_axes=NULL;
|
|
on_undo();
|
|
currentmode=ES_Normal;
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_freehand_axis_dragging(bool begin)
|
|
{
|
|
if(begin){
|
|
assert(currentmode==ES_Normal);
|
|
assert(old_origin==NULL);
|
|
assert(dragged_origin==NULL);
|
|
on_begin_action();
|
|
gla->setMouseTracking(true);
|
|
gla->grabKeyboard ();
|
|
old_origin=new CoordinateFrame(refsize);
|
|
old_origin->basecolor=Color4b(128,128,0,255);
|
|
old_origin->xcolor=Color4b(128,0,0,255);
|
|
old_origin->ycolor=Color4b(0,128,0,255);
|
|
old_origin->zcolor=Color4b(0,0,128,255);
|
|
old_origin->linewidth=1;
|
|
dragged_origin=new ActiveCoordinateFrame(refsize);
|
|
dragged_origin->basecolor=Color4b(255,255,0,255);
|
|
dragged_origin->xcolor=Color4b(255,0,0,255);
|
|
dragged_origin->ycolor=Color4b(0,255,0,255);
|
|
dragged_origin->zcolor=Color4b(0,0,255,255);
|
|
dragged_origin->linewidth=3;
|
|
dragged_origin->SetSnap(dialog->getSnap());
|
|
dialog->shoutShow();
|
|
currentmode=ES_FreehandAxisDragging;
|
|
} else {
|
|
assert(currentmode==ES_FreehandAxisDragging);
|
|
origin->SetPosition(dragged_origin->GetPosition());
|
|
origin->SetRotation(dragged_origin->GetRotation());
|
|
delete (old_origin); old_origin=NULL;
|
|
delete (dragged_origin); dragged_origin=NULL;
|
|
currentmode=ES_Normal;
|
|
gla->releaseKeyboard();
|
|
gla->setMouseTracking(false);
|
|
on_apply();
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_set_snap(float rot_snap_deg)
|
|
{
|
|
if(dragged_origin!=NULL)
|
|
dragged_origin->SetSnap(rot_snap_deg);
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_freehand_mesh_dragging(bool begin)
|
|
{
|
|
if(begin){
|
|
assert(currentmode==ES_Normal);
|
|
on_begin_action();
|
|
dragged_mesh = new DrawPhantom(mm,refsize);
|
|
currentmode=ES_FreehandMeshDragging;
|
|
} else {
|
|
assert(currentmode==ES_FreehandMeshDragging);
|
|
assert(dragged_mesh!=NULL);
|
|
Matrix44f a,b,c;
|
|
a.SetTranslate( dragged_mesh->manipulator->center);
|
|
b = dragged_mesh->manipulator->track.Matrix();
|
|
c.SetTranslate(-dragged_mesh->manipulator->center);
|
|
undosystem->SaveTR();
|
|
mm->cm.Tr = mm->cm.Tr * a * b * c;
|
|
on_apply();
|
|
delete dragged_mesh;
|
|
dragged_mesh=NULL;
|
|
currentmode=ES_Normal;
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_get_plane_from_selection(char normal,char preserve)
|
|
{
|
|
assert(mm->cm.sfn > 0);
|
|
|
|
Box3f bbox; //il bbox delle facce selezionate
|
|
std::vector< Point3f > selected_pts; //devo copiare i punti per il piano di fitting
|
|
|
|
tri::UpdateSelection<CMeshO>::ClearVertex(mm->cm);
|
|
tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(mm->cm);
|
|
CMeshO::VertexIterator vi;
|
|
for(vi=mm->cm.vert.begin();vi!=mm->cm.vert.end();++vi)
|
|
if(!(*vi).IsD() && (*vi).IsS() ){
|
|
Point3f p = mm->cm.Tr * (*vi).P();
|
|
bbox.Add(p);
|
|
selected_pts.push_back(p);
|
|
}
|
|
|
|
Plane3f plane;
|
|
PlaneFittingPoints(selected_pts,plane); //calcolo il piano di fitting
|
|
|
|
on_begin_action();
|
|
origin->SetPosition(plane.Projection(bbox.Center()));
|
|
origin->AlignWith(plane.Direction(),Point3f(0,0,0),normal,preserve);
|
|
on_apply();
|
|
|
|
gla->update();
|
|
}
|
|
|
|
void EditStraightener::on_update_show(bool db,bool ba, bool bl, bool bv, bool ca, bool cl, bool cv, bool m, bool r)
|
|
{
|
|
draw_bbox=db;
|
|
origin->drawaxis=ba;
|
|
origin->drawlabels=bl;
|
|
origin->drawvalues=bv;
|
|
if(dragged_origin!=NULL){
|
|
old_origin->drawaxis=ba;
|
|
old_origin->drawlabels=bl;
|
|
old_origin->drawvalues=bv;
|
|
dragged_origin->drawaxis=ca;
|
|
dragged_origin->drawlabels=cl;
|
|
dragged_origin->drawvalues=cv;
|
|
dragged_origin->drawmoves=m;
|
|
dragged_origin->drawrotations=r;
|
|
}
|
|
gla->update();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
DrawAxes::DrawAxes(char ch1,char ch2)
|
|
:firstchar(ch1),secondchar(ch2),
|
|
currentphase(DA_BEGIN),twoaxes(true),
|
|
first(Color4b(0,0,0,0)),second(Color4b(0,0,0,0)),
|
|
label1(QChar(ch1)),label2(QChar(ch2))
|
|
{
|
|
Color4b xc(255,128,128,255),yc(128,255,128,255),zc(128,128,255,255);
|
|
switch(ch1){
|
|
case 'X': first=Rubberband(xc); break;
|
|
case 'Y': first=Rubberband(yc); break;
|
|
case 'Z': first=Rubberband(zc); break;
|
|
default: assert(0);
|
|
}
|
|
switch(ch2){
|
|
case 'X': second=Rubberband(xc); break;
|
|
case 'Y': second=Rubberband(yc); break;
|
|
case 'Z': second=Rubberband(zc); break;
|
|
case ' ': twoaxes=false; break;
|
|
default: assert(0);
|
|
}
|
|
}
|
|
|
|
void DrawAxes::Render(QGLWidget *glw)
|
|
{
|
|
first.Render(glw);
|
|
second.Render(glw);
|
|
switch(currentphase){
|
|
case DA_BEGIN:
|
|
if(first.IsReady())
|
|
currentphase=DA_DONE_FIRST;
|
|
else first.RenderLabel(label1,glw);
|
|
break;
|
|
case DA_DONE_FIRST:
|
|
if(second.IsReady())
|
|
currentphase=DA_DONE_SECOND;
|
|
else second.RenderLabel(label2,glw);
|
|
break;
|
|
case DA_DONE_SECOND:
|
|
break;
|
|
default:
|
|
assert (0);
|
|
}
|
|
assert(!glGetError());
|
|
}
|
|
|
|
void DrawAxes::mouseMove(QPoint p)
|
|
{
|
|
if(IsReady())
|
|
return;
|
|
if(currentphase>=DA_DONE_FIRST)
|
|
second.Drag(p);
|
|
else
|
|
first.Drag(p);
|
|
}
|
|
|
|
void DrawAxes::mouseRelease(QPoint p)
|
|
{
|
|
if(IsReady())
|
|
return;
|
|
if(currentphase >= DA_DONE_FIRST)
|
|
second.Pin(p);
|
|
else
|
|
first.Pin(p);
|
|
}
|
|
|
|
bool DrawAxes::IsReady()
|
|
{
|
|
return currentphase >= ( twoaxes ? DA_DONE_SECOND : DA_DONE_FIRST);
|
|
}
|
|
|
|
void DrawAxes::GetAxes(Point3f &f1,Point3f &f2,Point3f &s1,Point3f &s2)
|
|
{
|
|
assert(IsReady());
|
|
first.GetPoints(f1,f2);
|
|
if(twoaxes){
|
|
second.GetPoints(s1,s2);
|
|
}else{
|
|
s1=s2=Point3f(0,0,0);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////
|
|
|
|
DrawPhantom::DrawPhantom(MeshModel* mm,float refsize)
|
|
{
|
|
glmesh.m = &(mm->cm);
|
|
glmesh.Update ();
|
|
tr=mm->cm.Tr;
|
|
manipulator = new Trackball();
|
|
manipulator->radius = refsize;
|
|
manipulator->center = Inverse(tr) * mm->cm.trBB().Center() ;
|
|
|
|
// rifaccio i modi senza le scalature
|
|
manipulator->ClearModes();
|
|
manipulator->modes[0] = NULL;
|
|
manipulator->modes[Trackball::BUTTON_LEFT] = new SphereMode ();
|
|
manipulator->modes[Trackball::BUTTON_LEFT |Trackball:: KEY_CTRL] = new PanMode ();
|
|
manipulator->modes[Trackball::BUTTON_MIDDLE] = new PanMode ();
|
|
manipulator->modes[Trackball::BUTTON_LEFT | Trackball::KEY_ALT] = new ZMode ();
|
|
manipulator->SetCurrentAction();
|
|
}
|
|
|
|
DrawPhantom::~DrawPhantom()
|
|
{
|
|
if(manipulator!=NULL) {
|
|
delete manipulator;
|
|
manipulator=NULL;
|
|
}
|
|
}
|
|
|
|
void DrawPhantom::Render()
|
|
{
|
|
glPushMatrix();
|
|
glPushAttrib (GL_ALL_ATTRIB_BITS);
|
|
|
|
glMultMatrix(tr);
|
|
|
|
manipulator->GetView();
|
|
manipulator->Apply(true);
|
|
|
|
float amb[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
|
|
float col[4] = { 0.5f, 0.5f, 0.8f, 1.0f };
|
|
float spe[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
glEnable (GL_LIGHTING);
|
|
glEnable (GL_LIGHT0);
|
|
glEnable (GL_NORMALIZE);
|
|
glEnable (GL_LINE_SMOOTH);
|
|
glEnable (GL_BLEND);
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glColor3f(0.4,0.4,0.8);
|
|
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, amb);
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col);
|
|
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,spe);
|
|
|
|
glmesh.Draw < GLW::DMWire , GLW::CMNone, GLW::TMNone > ();
|
|
|
|
glPopAttrib ();
|
|
glPopMatrix();
|
|
assert(!glGetError());
|
|
}
|
|
|
|
void DrawPhantom::MouseDown(int x, int y, /*Button*/ int button)
|
|
{
|
|
manipulator->MouseDown(x,y,button);
|
|
}
|
|
|
|
void DrawPhantom::MouseMove(int x, int y)
|
|
{
|
|
manipulator->MouseMove(x,y);
|
|
}
|
|
|
|
void DrawPhantom::MouseUp(int x, int y, /*Button */ int button)
|
|
{
|
|
manipulator->MouseUp(x, y, button);
|
|
}
|
|
|
|
void DrawPhantom::ButtonUp(int button)
|
|
{
|
|
manipulator->ButtonUp((Trackball::Button) button);
|
|
}
|
|
|
|
void DrawPhantom::ButtonDown(int button)
|
|
{
|
|
manipulator->ButtonDown((Trackball::Button) button);
|
|
}
|
|
|
|
////////////////////////////////////
|
|
|
|
UndoSystem::UndoSystem(EditStraightener const *e)
|
|
:marks(0),es(e),undotype_vec(),tr_vec()
|
|
{
|
|
}
|
|
|
|
void UndoSystem::BeginAction()
|
|
{
|
|
undotype_vec.push_back(US_MARK);
|
|
marks++;
|
|
if(marks>MAX_MARKS)
|
|
limitmarks();
|
|
if(marks==1)
|
|
es->dialog->SetUndo(true);
|
|
}
|
|
|
|
void UndoSystem::Undo()
|
|
{
|
|
assert(marks>0);
|
|
while(revert());
|
|
assert(undotype_vec.size()>0);
|
|
assert(undotype_vec.back()==US_MARK);
|
|
undotype_vec.pop_back();
|
|
marks--;
|
|
if(marks==0)
|
|
es->dialog->SetUndo(false);
|
|
}
|
|
|
|
bool UndoSystem::CanUndo()
|
|
{
|
|
return marks>0;
|
|
}
|
|
|
|
void UndoSystem::SaveTR()
|
|
{
|
|
assert(undotype_vec.size()>0);
|
|
undotype_vec.push_back(US_TR);
|
|
tr_vec.push_back(es->mm->cm.Tr);
|
|
}
|
|
|
|
void UndoSystem::SaveFreeze()
|
|
{
|
|
assert(undotype_vec.size()>0);
|
|
undotype_vec.push_back(US_FREEZE);
|
|
}
|
|
|
|
|
|
bool UndoSystem::revert()
|
|
{
|
|
assert(undotype_vec.size()>0);
|
|
UndoType undotype=undotype_vec.back();
|
|
switch(undotype){
|
|
case US_MARK:
|
|
return false;
|
|
case US_TR:
|
|
es->mm->cm.Tr=tr_vec.back();
|
|
tr_vec.pop_back();
|
|
break;
|
|
case US_FREEZE:
|
|
es->gla->setWindowModified(true);
|
|
tri::UpdatePosition<CMeshO>::Matrix(es->mm->cm, Inverse(es->mm->cm.Tr));
|
|
tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(es->mm->cm);
|
|
tri::UpdateBounding<CMeshO>::Box(es->mm->cm);
|
|
break;
|
|
}
|
|
undotype_vec.pop_back();
|
|
return true;
|
|
}
|
|
|
|
void UndoSystem::limitmarks()
|
|
{
|
|
if(undotype_vec.size()<=MAX_MARKS)
|
|
return;
|
|
assert(undotype_vec.size()>0);
|
|
assert(undotype_vec.front()==US_MARK);
|
|
// levo il mark di sotto
|
|
undotype_vec.pop_front();
|
|
marks--;
|
|
// levo tutto fino al prossimo mark (escluso)
|
|
while(true){
|
|
switch(undotype_vec.front()){
|
|
case US_MARK:
|
|
return;
|
|
case US_TR:
|
|
tr_vec.pop_front();
|
|
break;
|
|
case US_FREEZE:
|
|
break;
|
|
}
|
|
undotype_vec.pop_front();
|
|
}
|
|
}
|