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