/**************************************************************************** * 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 #include "rubberband.h" using namespace vcg; Rubberband::Rubberband(Color4b c) :color(c) { this->Reset(); } void Rubberband::Render(QGLWidget* gla) { if(have_to_pick){ assert(currentphase!=RUBBER_DRAGGED); Point3f pick_point; bool picked = Pick(QTLogicalToDevice(gla, qt_cursor.x()), QTLogicalToDevice(gla, 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 ) { Point2f qt_start_point = DevicePixelConvert(start); glColor(color); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, QTLogicalToDevice(gla,gla->width()), QTLogicalToDevice(gla,gla->height()), 0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glBegin(GL_LINES); glVertex(qt_start_point); glVertex2f(QTLogicalToDevice(gla, qt_cursor.x()), QTLogicalToDevice(gla, 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_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glColor(color); glLineWidth(2.0); glPointSize(4.0); glBegin(GL_LINES); glVertex(start); glVertex(end); glEnd(); glBegin(GL_POINTS); glVertex(start); glVertex(end); glEnd(); glDepthFunc(GL_GREATER); glLineWidth(1.0f); glPointSize(2.0f); glBegin(GL_LINES); glVertex(start); glVertex(end); glEnd(); glBegin(GL_POINTS); glVertex(start); glVertex(end); glEnd(); glDepthFunc(GL_LESS); } glPopAttrib(); assert(!glGetError()); } void Rubberband::RenderLine(QGLWidget* /*gla*/, Point3f AA, Point3f BB) { // Drawing of the line from AA to BB 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); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glColor(color); // IN FRONT OF SURFACE glDepthFunc(GL_LESS); glLineWidth(2.5); glPointSize(6.0); glBegin(GL_LINES); glVertex(AA); glVertex(BB); glEnd(); glBegin(GL_POINTS); glVertex(AA); glVertex(BB); glEnd(); // BEHIND SURFACE glDepthFunc(GL_GREATER); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); glLineWidth(1.5f); glPointSize(4.0f); glBegin(GL_LINES); glVertex(AA); glVertex(BB); glEnd(); glBegin(GL_POINTS); glVertex(AA); glVertex(BB); glEnd(); glDepthFunc(GL_LESS); 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; } Point2f Rubberband::DevicePixelConvert(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 Point2f(wx,vm[3]-wy); }