Subversion Repositories gelsvn

Rev

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

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