Subversion Repositories gelsvn

Rev

Rev 277 | Rev 392 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 277 Rev 299
1
#include <iostream>
1
#include <iostream>
2
#include "CGLA/CGLA.h"
2
#include "CGLA/CGLA.h"
3
#include "QuatTrackBall.h"
3
#include "QuatTrackBall.h"
4
 
4
 
5
#include "gel_glu.h"
5
#include "gel_glu.h"
6
#include "GLViewController.h"
6
#include "GLViewController.h"
7
 
7
 
8
 
8
 
9
using namespace std;
9
using namespace std;
10
using namespace CGLA;
10
using namespace CGLA;
11
 
11
 
12
namespace GLGraphics
12
namespace GLGraphics
13
{
13
{
14
    
14
    
15
    QuatTrackBall::QuatTrackBall(const Vec3f& _centre, 
15
    QuatTrackBall::QuatTrackBall(const Vec3f& _centre, 
16
			 float _eye_dist,
16
			 float _eye_dist,
17
			 unsigned _width, 
17
			 unsigned _width, 
18
			 unsigned _height):
18
			 unsigned _height):
19
	centre(_centre), width(_width), height(_height), 
19
	centre(_centre), width(_width), height(_height), 
20
	scale(0.5*_eye_dist), eye_dist(_eye_dist)
20
	scale(0.5*_eye_dist), eye_dist(_eye_dist)
21
	{
21
	{
22
	// This size should really be based on the distance from the center of
22
	// This size should really be based on the distance from the center of
23
	// rotation to the point on the object underneath the mouse.  That
23
	// rotation to the point on the object underneath the mouse.  That
24
	// point would then track the mouse as closely as possible.  This is a
24
	// point would then track the mouse as closely as possible.  This is a
25
	// simple example, though, so that is left as an exercise.
25
	// simple example, though, so that is left as an exercise.
26
	ballsize = 2.0f;
26
	ballsize = 2.0f;
27
	screen_centre = Vec2i(width/2, height/2);
27
	screen_centre = Vec2i(width/2, height/2);
28
	qrot = Quatf(0.0, 0.0, 0.0, 1.0);
28
	qrot = Quatf(0.0, 0.0, 0.0, 1.0);
29
	qinc = Quatf(0.0, 0.0, 0.0, 1.0);
29
	qinc = Quatf(0.0, 0.0, 0.0, 1.0);
30
	trans = Vec2f(0.0, 0.0);
30
	trans = Vec2f(0.0, 0.0);
31
    }
31
    }
32
    
32
    
33
    void QuatTrackBall::grab_ball(TrackBallAction act, const Vec2i& v)
33
    void QuatTrackBall::grab_ball(TrackBallAction act, const Vec2i& v)
34
    {
34
    {
-
 
35
    if(v[0] < 0 || v[0] >= static_cast<int>(width)
-
 
36
       || v[1] < 0 || v[1] >= static_cast<int>(height))
-
 
37
      return;      
-
 
38
 
35
      set_position(scalePoint(v));
39
	set_position(scalePoint(v));
36
      current_action = act;
40
	current_action = act;
37
    }
41
    }
38
    
42
    
39
    void QuatTrackBall::roll_ball(const Vec2i& v)
43
    void QuatTrackBall::roll_ball(const Vec2i& v)
40
    {
44
    {
-
 
45
    if(v[0] < 0 || v[0] >= static_cast<int>(width)
-
 
46
       || v[1] < 0 || v[1] >= static_cast<int>(height))
-
 
47
      return;      
-
 
48
 
41
	Vec2f w = scalePoint(v); 
49
	Vec2f w = scalePoint(v); 
42
	
50
	
43
	if(v[0] < 0 || v[0] >= static_cast<int>(width))
-
 
44
	  w[0] = last_pos[0];
-
 
45
	if(v[1] < 0 || v[1] >= static_cast<int>(height))
-
 
46
	  w[1] = last_pos[1];
-
 
47
 
-
 
48
	switch (current_action) 
51
	switch (current_action) 
49
	{
52
	{
50
			case ROTATE_ACTION:
53
			case ROTATE_ACTION:
51
	    rotate(w);
54
	    rotate(w);
52
	    break;
55
	    break;
53
	    
56
	    
54
			case PAN_ACTION:
57
			case PAN_ACTION:
55
	    pan(w);
58
	    pan(w);
56
	    break;
59
	    break;
57
	    
60
	    
58
			case ZOOM_ACTION:
61
			case ZOOM_ACTION:
59
	    zoom(w);
62
	    zoom(w);
60
	    break;
63
	    break;
61
	}
64
	}
62
	last_pos = w;	
65
	last_pos = w;	
63
    }
66
    }
64
    
67
    
65
    // Call this when the user does a mouse down.  
68
    // Call this when the user does a mouse down.  
66
    // Stop the trackball glide, then remember the mouse
69
    // Stop the trackball glide, then remember the mouse
67
    // down point (for a future rotate, pan or zoom).
70
    // down point (for a future rotate, pan or zoom).
68
    void QuatTrackBall::set_position(const Vec2f& _last_pos) 
71
    void QuatTrackBall::set_position(const Vec2f& _last_pos) 
69
    {
72
    {
70
	stop_spin();
73
	stop_spin();
71
	last_pos = _last_pos;
74
	last_pos = _last_pos;
72
    }
75
    }
73
    
76
    
74
    // Rotationaly spin the trackball by the current increment.
77
    // Rotationaly spin the trackball by the current increment.
75
    // Use this to implement rotational glide.
78
    // Use this to implement rotational glide.
76
    void QuatTrackBall::do_spin() 
79
    void QuatTrackBall::do_spin() 
77
    {
80
    {
78
	qrot = qrot*qinc;
81
	qrot = qrot*qinc;
79
    }
82
    }
80
    
83
    
81
    // Cease any rotational glide by zeroing the increment.
84
    // Cease any rotational glide by zeroing the increment.
82
    void QuatTrackBall::stop_spin() 
85
    void QuatTrackBall::stop_spin() 
83
    {
86
    {
84
	qinc.set(0.0, 0.0, 0.0, 1.0);
87
	qinc.set(0.0, 0.0, 0.0, 1.0);
85
    }
88
    }
86
    
89
    
87
    void QuatTrackBall::rotate(const Vec2f& new_v) 
90
    void QuatTrackBall::rotate(const Vec2f& new_v) 
88
    {
91
    {
89
	calcRotation(new_v);
92
	calcRotation(new_v);
90
	do_spin();	
93
	do_spin();	
91
    }
94
    }
92
    
95
    
93
    void QuatTrackBall::pan(const Vec2f& new_v) 
96
    void QuatTrackBall::pan(const Vec2f& new_v) 
94
    {
97
    {
95
	trans += (new_v - last_pos) * Vec2f(scale[0], scale[1]);
98
	trans += (new_v - last_pos) * Vec2f(scale[0], scale[1]);
96
    }
99
    }
97
    
100
    
98
    void QuatTrackBall::zoom(const Vec2f& new_v) 
101
    void QuatTrackBall::zoom(const Vec2f& new_v) 
99
    {
102
    {
100
	eye_dist += (new_v[1] - last_pos[1]) * scale[2];
103
	eye_dist += (new_v[1] - last_pos[1]) * scale[2];
101
	eye_dist = max(eye_dist, 0.01f);
104
	eye_dist = max(eye_dist, 0.01f);
102
    }
105
    }
103
    
106
    
104
    void QuatTrackBall::calcRotation(const Vec2f& new_pos) 
107
    void QuatTrackBall::calcRotation(const Vec2f& new_pos) 
105
    {
108
    {
106
	// Check for zero rotation
109
	// Check for zero rotation
107
	if (new_pos == last_pos) 
110
	if (new_pos == last_pos) 
108
	    qinc = Quatf(0.0f, 0.0f, 0.0f, 1.0f);
111
	    qinc = Quatf(0.0f, 0.0f, 0.0f, 1.0f);
109
	else
112
	else
110
	{
113
	{
111
		// Form two vectors based on input points, find rotation axis
114
		// Form two vectors based on input points, find rotation axis
112
		Vec3f p1 = Vec3f(new_pos[0], new_pos[1], projectToSphere(new_pos));
115
		Vec3f p1 = Vec3f(new_pos[0], new_pos[1], projectToSphere(new_pos));
113
		Vec3f p2 = Vec3f(last_pos[0], last_pos[1], projectToSphere(last_pos));
116
		Vec3f p2 = Vec3f(last_pos[0], last_pos[1], projectToSphere(last_pos));
-
 
117
        qinc.make_rot(normalize(p1), normalize(p2));
-
 
118
/*
-
 
119
		Vec3f q = cross(p1, p2);		// axis of rotation from p1 and p2 
-
 
120
		float L = sqrt(1.0f-dot(q,q) / (dot(p1,p1) * dot(p2,p2)));
114
		
121
		
-
 
122
		q.normalize();				// q' = axis of rotation 
-
 
123
		q *= sqrt((1 - L)/2);	// q' = q' * sin(phi)
-
 
124
		
115
		qinc.make_rot(normalize(p1), normalize(p2));
125
		qinc.set(q[0],q[1],q[2],sqrt((1 + L)/2));
-
 
126
*/
116
	}
127
	}
117
    }
128
    }
118
    
129
    
119
    // Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
130
    // Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
120
    // if we are away from the center of the sphere.
131
    // if we are away from the center of the sphere.
121
    float QuatTrackBall::projectToSphere(const Vec2f& v) 
132
    float QuatTrackBall::projectToSphere(const Vec2f& v) 
122
    {
133
    {
123
	float d, t, z;
134
#ifndef M_SQRT_2
-
 
135
	  const double M_SQRT_2 = 0.707106781187;
-
 
136
#endif
124
	
137
 
125
	d = v.length();
138
      float d = v.length();
-
 
139
      float t = ballsize*M_SQRT_2;
-
 
140
      float z;
126
	
141
  
127
	// Inside sphere 
142
      // Inside sphere 
128
	if (d < ballsize * 0.70710678118654752440) {   
143
      if(d < ballsize) 
129
	    z = sqrt(ballsize*ballsize - d*d);
144
        z = sqrt(ballsize*ballsize - d*d);
-
 
145
      else if(d < t)
130
	}
146
        z = 0.0;
131
	// On hyperbola 
147
      // On hyperbola 
132
	else {           
148
      else 
133
	    t = ballsize / 1.41421356237309504880;
-
 
134
	    z = t*t / d;
149
        z = t*t/d;
135
	}
-
 
136
	
150
 
137
	return z;
151
      return z;
138
    }
152
    }
139
    
153
    
140
    // Scales integer point to the range [-1, 1]
154
    // Scales integer point to the range [-1, 1]
141
    Vec2f QuatTrackBall::scalePoint(const Vec2i& v) const
155
    Vec2f QuatTrackBall::scalePoint(const Vec2i& v) const
142
    {
156
    {
143
	Vec2f w(v[0],height - v[1]);
157
	Vec2f w(v[0],height - v[1]);
144
	w -= Vec2f(screen_centre);
158
	w -= Vec2f(screen_centre);
145
	w /= Vec2f(width,height);
159
	w /= Vec2f(width,height);
146
	w = CGLA::v_min(Vec2f(1.0f), CGLA::v_max(Vec2f(-1), 2*w));
160
	w = CGLA::v_min(Vec2f(1.0f), CGLA::v_max(Vec2f(-1), 2*w));
147
	return w; 
161
	return w; 
148
    }
162
    }
149
    
163
    
150
    void QuatTrackBall::get_view_param(Vec3f& eye, Vec3f& _centre, Vec3f& up) const
164
    void QuatTrackBall::get_view_param(Vec3f& eye, Vec3f& _centre, Vec3f& up) const
151
    {
165
    {
152
	up  = qrot.apply_unit(Vec3f(0,1,0));
166
	up  = qrot.apply_unit(Vec3f(0,1,0));
153
	Vec3f right = qrot.apply(Vec3f(1,0,0));
167
	Vec3f right = qrot.apply(Vec3f(1,0,0));
154
	_centre = centre - up * trans[1] - right * trans[0]; 
168
	_centre = centre - up * trans[1] - right * trans[0]; 
155
	eye = qrot.apply_unit(Vec3f(0,0,1)*eye_dist) + _centre;
169
	eye = qrot.apply_unit(Vec3f(0,0,1)*eye_dist) + _centre;
156
    }
170
    }
157
    
171
    
158
    
172
    
159
    // Modify the current gl matrix by the trackball rotation and translation.
173
    // Modify the current gl matrix by the trackball rotation and translation.
160
    void QuatTrackBall::set_gl_modelview() const
174
    void QuatTrackBall::set_gl_modelview() const
161
    {
175
    {
162
	glMatrixMode(GL_MODELVIEW);
176
	glMatrixMode(GL_MODELVIEW);
163
	glLoadIdentity();
177
	glLoadIdentity();
164
	Vec3f eye;
178
	Vec3f eye;
165
	Vec3f _centre;
179
	Vec3f _centre;
166
	Vec3f up;
180
	Vec3f up;
167
	get_view_param(eye, _centre, up);
181
	get_view_param(eye, _centre, up);
168
	gluLookAt(eye[0], eye[1], eye[2],
182
	gluLookAt(eye[0], eye[1], eye[2],
169
		  _centre[0], _centre[1], _centre[2], 
183
		  _centre[0], _centre[1], _centre[2], 
170
		  up[0],up[1],up[2]);
184
		  up[0],up[1],up[2]);
171
    }
185
    }
172
    
186
    
173
    bool QuatTrackBall::is_spinning() const
187
    bool QuatTrackBall::is_spinning() const
174
    {
188
    {
175
	static const Quatf null_quat(0,0,0,1);
189
	static const Quatf null_quat(0,0,0,1);
176
	if(qinc != null_quat)
190
	if(!(qinc == null_quat))
177
	    return true;
191
	    return true;
178
	return false;
192
	return false;
179
    }
193
    }
180
}
194
}
181
 
195