Subversion Repositories gelsvn

Rev

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

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