1 /**********************************************************************
2
3 arcball.cpp
4
5
6 --------------------------------------------------
7
8 GLUI User Interface Toolkit (LGPL)
9 Copyright (c) 1998 Paul Rademacher
10 Feb 1998, Paul Rademacher (rademach@cs.unc.edu)
11 Oct 2003, Nigel Stewart - GLUI Code Cleaning
12
13 WWW: http://sourceforge.net/projects/glui/
14 Forums: http://sourceforge.net/forum/?group_id=92496
15
16 This library is free software; you can redistribute it and/or
17 modify it under the terms of the GNU Lesser General Public
18 License as published by the Free Software Foundation; either
19 version 2.1 of the License, or (at your option) any later version.
20
21 This library is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 Lesser General Public License for more details.
25
26 You should have received a copy of the GNU Lesser General Public
27 License along with this library; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
30 **********************************************************************/
31
32 #include "arcball.h"
33
34 #include <cstdio>
35
36
37 /**************************************** Arcball::Arcball() ****/
38 /* Default (void) constructor for Arcball */
39
Arcball()40 Arcball::Arcball()
41 {
42 rot_ptr = &rot;
43 init();
44 }
45
46 /**************************************** Arcball::Arcball() ****/
47 /* Takes as argument a mat4 to use instead of the internal rot */
48
Arcball(mat4 * mtx)49 Arcball::Arcball(mat4 *mtx)
50 {
51 rot_ptr = mtx;
52 }
53
54
55 /**************************************** Arcball::Arcball() ****/
56 /* A constructor that accepts the screen center and arcball radius*/
57
Arcball(const vec2 & _center,float _radius)58 Arcball::Arcball(const vec2 &_center, float _radius)
59 {
60 rot_ptr = &rot;
61 init();
62 set_params(_center, _radius);
63 }
64
65
66 /************************************** Arcball::set_params() ****/
67
set_params(const vec2 & _center,float _radius)68 void Arcball::set_params(const vec2 &_center, float _radius)
69 {
70 center = _center;
71 radius = _radius;
72 }
73
74 /*************************************** Arcball::init() **********/
75
init()76 void Arcball::init()
77 {
78 center.set( 0.0, 0.0 );
79 radius = 1.0;
80 q_now = quat_identity();
81 *rot_ptr = identity3D();
82 q_increment = quat_identity();
83 rot_increment = identity3D();
84 is_mouse_down = false;
85 is_spinning = false;
86 damp_factor = 0.0;
87 zero_increment = true;
88 }
89
90 /*********************************** Arcball::mouse_to_sphere() ****/
91
mouse_to_sphere(const vec2 & p)92 vec3 Arcball::mouse_to_sphere(const vec2 &p)
93 {
94 float mag;
95 vec2 v2 = (p - center) / radius;
96 vec3 v3( v2[0], v2[1], 0.0 );
97
98 mag = v2*v2;
99
100 if ( mag > 1.0 )
101 v3.normalize();
102 else
103 v3[VZ] = (float) sqrt( 1.0 - mag );
104
105 /* Now we add constraints - X takes precedence over Y */
106 if ( constraint_x )
107 {
108 v3 = constrain_vector( v3, vec3( 1.0, 0.0, 0.0 ));
109 }
110 else if ( constraint_y )
111 {
112 v3 = constrain_vector( v3, vec3( 0.0, 1.0, 0.0 ));
113 }
114
115 return v3;
116 }
117
118
119 /************************************ Arcball::constrain_vector() ****/
120
constrain_vector(const vec3 & vector,const vec3 & axis)121 vec3 Arcball::constrain_vector(const vec3 &vector, const vec3 &axis)
122 {
123 return (vector-(vector*axis)*axis).normalize();
124 }
125
126 /************************************ Arcball::mouse_down() **********/
127
mouse_down(int x,int y)128 void Arcball::mouse_down(int x, int y)
129 {
130 down_pt.set( (float)x, (float) y );
131 is_mouse_down = true;
132
133 q_increment = quat_identity();
134 rot_increment = identity3D();
135 zero_increment = true;
136 }
137
138
139 /************************************ Arcball::mouse_up() **********/
140
mouse_up()141 void Arcball::mouse_up()
142 {
143 q_now = q_drag * q_now;
144 is_mouse_down = false;
145 }
146
147
148 /********************************** Arcball::mouse_motion() **********/
149
mouse_motion(int x,int y,int shift,int ctrl,int alt)150 void Arcball::mouse_motion(int x, int y, int shift, int ctrl, int alt)
151 {
152 /* Set the X constraint if CONTROL key is pressed, Y if ALT key */
153 set_constraints( ctrl != 0, alt != 0 );
154
155 vec2 new_pt( (float)x, (float) y );
156 vec3 v0 = mouse_to_sphere( down_pt );
157 vec3 v1 = mouse_to_sphere( new_pt );
158
159 vec3 cross = v0^v1;
160
161 q_drag.set( cross, v0 * v1 );
162
163 // *rot_ptr = (q_drag * q_now).to_mat4();
164 mat4 temp = q_drag.to_mat4();
165 *rot_ptr = *rot_ptr * temp;
166
167 down_pt = new_pt;
168
169 /* We keep a copy of the current incremental rotation (= q_drag) */
170 q_increment = q_drag;
171 rot_increment = q_increment.to_mat4();
172
173 set_constraints(false, false);
174
175 if ( q_increment.s < .999999 )
176 {
177 is_spinning = true;
178 zero_increment = false;
179 }
180 else
181 {
182 is_spinning = false;
183 zero_increment = true;
184 }
185 }
186
187
188 /********************************** Arcball::mouse_motion() **********/
189
mouse_motion(int x,int y)190 void Arcball::mouse_motion(int x, int y)
191 {
192 mouse_motion(x, y, 0, 0, 0);
193 }
194
195
196 /***************************** Arcball::set_constraints() **********/
197
set_constraints(bool _constraint_x,bool _constraint_y)198 void Arcball::set_constraints(bool _constraint_x, bool _constraint_y)
199 {
200 constraint_x = _constraint_x;
201 constraint_y = _constraint_y;
202 }
203
204 /***************************** Arcball::idle() *********************/
205
idle()206 void Arcball::idle()
207 {
208 if (is_mouse_down)
209 {
210 is_spinning = false;
211 zero_increment = true;
212 }
213
214 if (damp_factor < 1.0f)
215 q_increment.scale_angle(1.0f - damp_factor);
216
217 rot_increment = q_increment.to_mat4();
218
219 if (q_increment.s >= .999999f)
220 {
221 is_spinning = false;
222 zero_increment = true;
223 }
224 }
225
226
227 /************************ Arcball::set_damping() *********************/
228
set_damping(float d)229 void Arcball::set_damping(float d)
230 {
231 damp_factor = d;
232 }
233
234
235
236
237
238