Developer Documentation
GLTrackball.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 
52 //=============================================================================
53 //
54 // CLASS GLTrackball - IMPLEMENTATION
55 //
56 //=============================================================================
57 
58 //== INCLUDES =================================================================
59 
60 
61 #include "GLTrackball.hh"
62 
63 
64 //== NAMESPACES ===============================================================
65 
66 
67 namespace ACG {
68 
69 
70 //== IMPLEMENTATION ==========================================================
71 
72 
73 GLTrackball::
74 GLTrackball(GLState& _state)
75  : glstate_(_state),
76  center_(0,0,0) ,
77  last_point_ok_(false),
78  action_(ROTATION)
79 {
80  for (int i=0; i<10; ++i)
81  button_down_[i] = false;
82 }
83 
84 
85 //-----------------------------------------------------------------------------
86 
87 
88 void
89 GLTrackball::mouse_press(int button, int x, int y)
90 {
91  last_point_2D_ = ACG::Vec2i(x, y);
92  last_point_ok_ = map_to_sphere(last_point_2D_, last_point_3D_);
93 
94  button_down_[button] = true;
95 }
96 
97 
98 //-----------------------------------------------------------------------------
99 
100 
101 void
102 GLTrackball::mouse_release(int button, int /* x */ , int /* y */ )
103 {
104  last_point_ok_ = false;
105  button_down_[button] = false;
106 
107  // GLUT: button 3 or 4 -> mouse wheel clicked
108  if (button == 3)
109  zoom(0, (int)(last_point_2D_[1] - 0.05*glstate_.viewport_width()));
110  else if (button == 4)
111  zoom(0, (int)(last_point_2D_[1] + 0.05*glstate_.viewport_width()));
112 }
113 
114 
115 //-----------------------------------------------------------------------------
116 
117 
118 void
119 GLTrackball::mouse_move(int x, int y)
120 {
121  if (button_down_[0] && button_down_[1])
122  action_ = ZOOM;
123  else if (button_down_[0])
124  action_ = ROTATION;
125  else if (button_down_[1])
126  action_ = TRANSLATION;
127 
128  switch (action_)
129  {
130  case ROTATION: rotation(x, y); break;
131  case TRANSLATION: translation(x, y); break;
132  case ZOOM: zoom(x, y); break;
133  }
134 
135  last_point_2D_ = ACG::Vec2i(x, y);
136  last_point_ok_ = map_to_sphere(last_point_2D_, last_point_3D_);
137 }
138 
139 
140 //-----------------------------------------------------------------------------
141 
142 
143 void
144 GLTrackball::rotation(int x, int y)
145 {
146  if (last_point_ok_)
147  {
148  Vec2i new_point_2D_;
149  Vec3f new_point_3D_;
150  bool new_point_ok_;
151 
152  new_point_2D_ = ACG::Vec2i(x, y);
153  new_point_ok_ = map_to_sphere(new_point_2D_, new_point_3D_);
154 
155  if (new_point_ok_)
156  {
157  Vec3f axis = (last_point_3D_ % new_point_3D_);
158  float cos_angle = (last_point_3D_ | new_point_3D_);
159 
160  if (fabs(cos_angle) < 1.0)
161  {
162  double angle = 2.0*acos(cos_angle) * 180.0 / M_PI;
163 
164  Vec3d t = glstate_.modelview().transform_point(center_);
165  glstate_.translate(-t[0], -t[1], -t[2], MULT_FROM_LEFT);
166  glstate_.rotate(angle, axis[0], axis[1], axis[2], MULT_FROM_LEFT);
167  glstate_.translate( t[0], t[1], t[2], MULT_FROM_LEFT);
168  }
169  }
170  }
171 }
172 
173 
174 //-----------------------------------------------------------------------------
175 
176 
177 void
178 GLTrackball::translation(int x, int y)
179 {
180  double dx = double(x - last_point_2D_[0]);
181  double dy = double(y - last_point_2D_[1]);
182 
183  double z = glstate_.modelview().transform_point(center_)[2];
184  double w = double(glstate_.viewport_width());
185  double h = double(glstate_.viewport_height());
186  double fovy = double(glstate_.fovy());
187  double nearpl = double(glstate_.near_plane());
188 
189  double aspect = w / h;
190  double top = double(tan(fovy/2.0*M_PI/180.0) * nearpl);
191  double right = aspect*top;
192 
193  glstate_.translate(-2.0*dx/w*right/nearpl*z,
194  2.0*dy/h*top/nearpl*z,
195  0.0,
196  MULT_FROM_LEFT);
197 }
198 
199 
200 //-----------------------------------------------------------------------------
201 
202 
203 void
204 GLTrackball::zoom(int /* x */ , int y)
205 {
206  double dy = double(y - last_point_2D_[1]);
207  double z = glstate_.modelview().transform_point(center_)[2];
208  double h = double(glstate_.viewport_height());
209 
210  glstate_.translate(0.0,
211  0.0,
212  -2.0*dy/h*z,
213  MULT_FROM_LEFT);
214 }
215 
216 
217 //-----------------------------------------------------------------------------
218 
219 
220 bool
221 GLTrackball::map_to_sphere(const Vec2i& _point, Vec3f& _result)
222 {
223  float width = float(glstate_.viewport_width());
224  float height = float(glstate_.viewport_height());
225 
226  if ( (_point[0] >= 0) && (_point[0] <= width) &&
227  (_point[1] >= 0) && (_point[1] <= height) )
228  {
229  double x = (_point[0] - 0.5*width) / width;
230  double y = (0.5*height - _point[1]) / height;
231  double sinx = sin(M_PI * x * 0.5);
232  double siny = sin(M_PI * y * 0.5);
233  double sinx2siny2 = sinx * sinx + siny * siny;
234 
235  _result[0] = float(sinx);
236  _result[1] = float(siny);
237  _result[2] = sinx2siny2 < 1.0 ? float( sqrt(1.0 - sinx2siny2) ) : 0.0f;
238 
239  return true;
240  }
241  else return false;
242 }
243 
244 
245 //=============================================================================
246 } // namespace ACG
247 //=============================================================================
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x&#39;,y&#39;,z&#39;,1) = M * (x,y,z,1)
Definition: Matrix4x4T.cc:202
int viewport_width() const
get viewport width
Definition: GLState.hh:825
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:531
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:104
T angle(T _cos_angle, T _sin_angle)
Definition: MathDefs.hh:145
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void rotate(double _angle, double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
rotate around axis (_x, _y, _z) by _angle
Definition: GLState.cc:562
double near_plane() const
get near clipping distance
Definition: GLState.hh:836
DLLEXPORT double fovy(int _viewer)
Get field of view angle.
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:794
double fovy() const
get field of view in y direction
Definition: GLState.cc:864
int viewport_height() const
get viewport height
Definition: GLState.hh:827
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127