Subversion Repositories gelsvn

Rev

Rev 125 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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