/**************************************************************************** * 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: not supported by cvs2svn $ ****************************************************************************/ #include #include #include #include "rubberband.h" using namespace vcg; Rubberband::Rubberband(Color4b c) :color(c),currentphase(RUBBER_BEGIN),qt_cursor(), start(0,0,0),end(0,0,0),have_to_pick(false),font() { font.setFamily("Helvetica"); font.setPixelSize(13); } void Rubberband::Render(QGLWidget* gla) { if(have_to_pick){ assert(currentphase!=RUBBER_DRAGGED); Point3f pick_point; bool picked = Pick(qt_cursor.x(), gla->height() - qt_cursor.y(), pick_point); if(picked){ // we have not picked the background have_to_pick=false; switch(currentphase){ case RUBBER_BEGIN: start = pick_point; gla->setMouseTracking(true); currentphase = RUBBER_DRAGGING; break; case RUBBER_DRAGGING: if(pick_point==start){ have_to_pick=true; break; } end = pick_point; gla->setMouseTracking(false); currentphase = RUBBER_DRAGGED; break; default: assert(0); } } } if(currentphase==RUBBER_BEGIN) return; // Drawing of the current line 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); glDepthMask(false); glLineWidth(2.5); glPointSize(5.0); if(currentphase==RUBBER_DRAGGING ) { Point3f qt_start_point; qt_start_point = PixelConvert(start); glColor(color); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,gla->width(),gla->height(),0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glBegin(GL_LINES); glVertex2f(qt_start_point[0],qt_start_point[1]); glVertex2f(qt_cursor.x(),qt_cursor.y()); glEnd(); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } else { assert(currentphase == RUBBER_DRAGGED); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glColor(color); glBegin(GL_LINES); glVertex(start); glVertex(end); glEnd(); glBegin(GL_POINTS); glVertex(start); glVertex(end); glEnd(); glDisable(GL_DEPTH_TEST); glLineWidth(0.7); glPointSize(1.4); glBegin(GL_LINES); glVertex(start); glVertex(end); glEnd(); glBegin(GL_POINTS); glVertex(start); glVertex(end); glEnd(); } glPopAttrib(); assert(!glGetError()); } void Rubberband::Drag(QPoint p) { if(currentphase==RUBBER_DRAGGING) qt_cursor=p; } void Rubberband::Pin(QPoint p) { if(IsReady()) return; qt_cursor=p; have_to_pick=true; } void Rubberband::Reset() { currentphase = RUBBER_BEGIN; qt_cursor = QPoint(); start = Point3f(0,0,0); end = Point3f(0,0,0); have_to_pick = false; } bool Rubberband::IsReady() { return currentphase==RUBBER_DRAGGED; } void Rubberband::GetPoints(Point3f &s,Point3f &e) { assert(IsReady()); s=start; e=end; } void Rubberband::RenderLabel(QString text,QGLWidget* gla) { if(currentphase==RUBBER_BEGIN) return; int x,y; if(currentphase==RUBBER_DRAGGING){ x=qt_cursor.x()+16; y=qt_cursor.y()+16; } else { Point3f qt_start = PixelConvert(start); Point3f qt_end = PixelConvert(end); if(qt_start[0]>qt_end[0]){ x=int(qt_start[0]+5); y=int(qt_start[1]); }else{ x=int(qt_end[0]+5); y=int(qt_end[1]); } } QFontMetrics fm(font); QRect brec=fm.boundingRect(text); glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT ); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,gla->width(),gla->height(),0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glColor4f(0,0,0,0.5); glBegin(GL_QUADS); glVertex2f(x+brec.left(),y+brec.bottom()); glVertex2f(x+brec.right(),y+brec.bottom()); glVertex2f(x+brec.right(),y+brec.top()); glVertex2f(x+brec.left(),y+brec.top()); glEnd(); int offset=2; glColor4f(0,0,0,0.2); glBegin(GL_QUADS); glVertex2f(x+brec.left()-offset,y+brec.bottom()+offset); glVertex2f(x+brec.right()+offset,y+brec.bottom()+offset); glVertex2f(x+brec.right()+offset,y+brec.top()-offset); glVertex2f(x+brec.left()-offset,y+brec.top()-offset); glEnd(); glColor3f(1,1,1); gla->renderText(x,y,0.99f,text,font); glGetError();//Due to buggy glrenderText() glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } Point3f Rubberband::PixelConvert(const Point3f p) { GLint vm[4]; GLdouble mm[16]; GLdouble pm[16]; glGetIntegerv(GL_VIEWPORT, vm); glGetDoublev(GL_MODELVIEW_MATRIX, mm); glGetDoublev(GL_PROJECTION_MATRIX, pm); GLdouble wx,wy,wz; gluProject(p[0], p[1], p[2], mm, pm, vm, &wx, &wy, &wz); return Point3f(wx,vm[3]-wy,wz); }