1 /****************************************************************************
2  * MeshLab                                                           o o     *
3  * A versatile mesh processing toolbox                             o     o   *
4  *                                                                _   O  _   *
5  * Copyright(C) 2008                                                \/)\/    *
6  * Visual Computing Lab                                            /\/|      *
7  * ISTI - Italian National Research Council                           |      *
8  *                                                                    \      *
9  * All rights reserved.                                                      *
10  *                                                                           *
11  * This program is free software; you can redistribute it and/or modify      *
12  * it under the terms of the GNU General Public License as published by      *
13  * the Free Software Foundation; either version 2 of the License, or         *
14  * (at your option) any later version.                                       *
15  *                                                                           *
16  * This program is distributed in the hope that it will be useful,           *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19  * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20  * for more details.                                                         *
21  *                                                                           *
22  ****************************************************************************/
23 /****************************************************************************
24   History
25 $Log: not supported by cvs2svn $
26 
27 ****************************************************************************/
28 
29 #include <GL/glew.h>
30 #include <wrap/gl/space.h>
31 #include <wrap/gl/picking.h>
32 #include <wrap/qt/device_to_logical.h>
33 
34 #include "rubberband.h"
35 
36 using namespace vcg;
37 
Rubberband(Color4b c)38 Rubberband::Rubberband(Color4b c)
39 :color(c)
40 {
41 	this->Reset();
42 }
43 
Render(QGLWidget * gla)44 void Rubberband::Render(QGLWidget* gla)
45 {
46   if(have_to_pick){
47     assert(currentphase!=RUBBER_DRAGGED);
48     Point3f pick_point;
49     bool picked = Pick(QTLogicalToDevice(gla, qt_cursor.x()), QTLogicalToDevice(gla, gla->height() - qt_cursor.y()), pick_point);
50     if(picked){ // we have not picked the background
51       have_to_pick=false;
52       switch(currentphase){
53         case RUBBER_BEGIN:
54           start = pick_point;
55           gla->setMouseTracking(true);
56           currentphase = RUBBER_DRAGGING;
57           break;
58         case RUBBER_DRAGGING:
59           if(pick_point==start){
60               have_to_pick=true;
61             break;
62           }
63           end = pick_point;
64           gla->setMouseTracking(false);
65           currentphase = RUBBER_DRAGGED;
66           break;
67         default:
68           assert(0);
69       }
70     }
71   }
72 
73   if(currentphase==RUBBER_BEGIN) return;
74 
75   // Drawing of the current line
76   glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT);
77   glDisable(GL_LIGHTING);
78   glDisable(GL_TEXTURE_2D);
79   glDepthMask(false);
80   glLineWidth(2.5);
81   glPointSize(5.0);
82 
83   if(currentphase==RUBBER_DRAGGING )
84   {
85     Point2f qt_start_point = DevicePixelConvert(start);
86     glColor(color);
87     glMatrixMode(GL_PROJECTION);
88     glPushMatrix();
89     glLoadIdentity();
90     gluOrtho2D(0, QTLogicalToDevice(gla,gla->width()), QTLogicalToDevice(gla,gla->height()), 0);
91     glMatrixMode(GL_MODELVIEW);
92     glPushMatrix();
93     glLoadIdentity();
94     glDisable(GL_DEPTH_TEST);
95     glBegin(GL_LINES);
96       glVertex(qt_start_point);
97       glVertex2f(QTLogicalToDevice(gla, qt_cursor.x()), QTLogicalToDevice(gla, qt_cursor.y()));
98     glEnd();
99     glEnable(GL_DEPTH_TEST);
100     glMatrixMode(GL_PROJECTION);
101     glPopMatrix();
102     glMatrixMode(GL_MODELVIEW);
103     glPopMatrix();
104   }
105   else
106   {
107     assert(currentphase == RUBBER_DRAGGED);
108     glEnable(GL_BLEND);
109 	glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
110     glEnable(GL_LINE_SMOOTH);
111     glEnable(GL_POINT_SMOOTH);
112     glColor(color);
113 	glLineWidth(2.0);
114 	glPointSize(4.0);
115     glBegin(GL_LINES);
116       glVertex(start);
117       glVertex(end);
118     glEnd();
119     glBegin(GL_POINTS);
120       glVertex(start);
121       glVertex(end);
122     glEnd();
123 	glDepthFunc(GL_GREATER);
124     glLineWidth(1.0f);
125     glPointSize(2.0f);
126     glBegin(GL_LINES);
127       glVertex(start);
128       glVertex(end);
129     glEnd();
130     glBegin(GL_POINTS);
131       glVertex(start);
132       glVertex(end);
133     glEnd();
134 	glDepthFunc(GL_LESS);
135   }
136 
137 
138   glPopAttrib();
139   assert(!glGetError());
140 }
141 
RenderLine(QGLWidget *,Point3f AA,Point3f BB)142 void Rubberband::RenderLine(QGLWidget* /*gla*/, Point3f AA, Point3f BB)
143 {
144 	// Drawing of the line from AA to BB
145 	glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT);
146 	glDisable(GL_LIGHTING);
147 	glDisable(GL_TEXTURE_2D);
148 	glDepthMask(false);
149 	glEnable(GL_LINE_SMOOTH);
150 	glEnable(GL_POINT_SMOOTH);
151 	glColor(color);
152 
153 	// IN FRONT OF SURFACE
154 	glDepthFunc(GL_LESS);
155 	glLineWidth(2.5);
156 	glPointSize(6.0);
157 	glBegin(GL_LINES);
158 	glVertex(AA);
159 	glVertex(BB);
160 	glEnd();
161 	glBegin(GL_POINTS);
162 	glVertex(AA);
163 	glVertex(BB);
164 	glEnd();
165 
166 	// BEHIND SURFACE
167 	glDepthFunc(GL_GREATER);
168 	glEnable(GL_BLEND);
169 	glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
170 	glLineWidth(1.5f);
171 	glPointSize(4.0f);
172 	glBegin(GL_LINES);
173 	glVertex(AA);
174 	glVertex(BB);
175 	glEnd();
176 	glBegin(GL_POINTS);
177 	glVertex(AA);
178 	glVertex(BB);
179 	glEnd();
180 
181 	glDepthFunc(GL_LESS);
182 	glPopAttrib();
183 	assert(!glGetError());
184 }
185 
Drag(QPoint p)186 void Rubberband::Drag(QPoint p)
187 {
188   if(currentphase==RUBBER_DRAGGING)
189     qt_cursor=p;
190 }
191 
Pin(QPoint p)192 void Rubberband::Pin(QPoint p)
193 {
194   if(IsReady())
195     return;
196   qt_cursor=p;
197   have_to_pick=true;
198 }
199 
Reset()200 void Rubberband::Reset()
201 {
202   currentphase = RUBBER_BEGIN;
203   qt_cursor = QPoint();
204   start = Point3f(0,0,0);
205   end = Point3f(0,0,0);
206   have_to_pick = false;
207 }
208 
IsReady()209 bool Rubberband::IsReady()
210 {
211   return currentphase==RUBBER_DRAGGED;
212 }
213 
GetPoints(Point3f & s,Point3f & e)214 void Rubberband::GetPoints(Point3f &s,Point3f &e)
215 {
216   assert(IsReady());
217   s=start;
218   e=end;
219 }
220 
DevicePixelConvert(const Point3f p)221 Point2f Rubberband::DevicePixelConvert(const Point3f p)
222 {
223   GLint vm[4];
224   GLdouble mm[16];
225   GLdouble pm[16];
226   glGetIntegerv(GL_VIEWPORT, vm);
227   glGetDoublev(GL_MODELVIEW_MATRIX, mm);
228   glGetDoublev(GL_PROJECTION_MATRIX, pm);
229   GLdouble wx,wy,wz;
230   gluProject(p[0], p[1], p[2], mm, pm, vm, &wx, &wy, &wz);
231   return Point2f(wx,vm[3]-wy);
232 }
233