Subversion Repositories gelsvn

Rev

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

Rev 306 Rev 323
1
#ifndef __CGLA_ARITHQUAT_H__
1
#ifndef __CGLA_ARITHQUAT_H__
2
#define __CGLA_ARITHQUAT_H__
2
#define __CGLA_ARITHQUAT_H__
3
 
3
 
4
#include "CGLA.h"
4
#include "CGLA.h"
-
 
5
#include "ArithSqMatFloat.h"
5
#include <cmath>
6
#include <cmath>
6
 
7
 
7
namespace CGLA {
8
namespace CGLA {
8
 
9
 
9
  /** \brief A T based Quaterinion class. 
10
  /** \brief A T based Quaterinion class. 
10

11

11
	Quaternions are algebraic entities useful for rotation. */
12
	Quaternions are algebraic entities useful for rotation. */
12
 
13
 
13
	template<class T, class V, class Q>
14
	template<class T, class V, class Q>
14
  class ArithQuat
15
  class ArithQuat
15
  {
16
  {
16
  public:
17
  public:
17
 
18
 
18
    /// Vector part of quaternion
19
    /// Vector part of quaternion
19
    V qv;
20
    V qv;
20
 
21
 
21
    /// Scalar part of quaternion
22
    /// Scalar part of quaternion
22
    T qw;
23
    T qw;
23
 
24
 
24
    /// Construct undefined quaternion
25
    /// Construct undefined quaternion
25
#ifndef NDEBUG
26
#ifndef NDEBUG
26
    ArithQuat() : qw(CGLA_INIT_VALUE) {}
27
    ArithQuat() : qw(CGLA_INIT_VALUE) {}
27
#else
28
#else
28
    ArithQuat() {}
29
    ArithQuat() {}
29
#endif
30
#endif
30
 
31
 
31
    /// Construct quaternion from vector and scalar
32
    /// Construct quaternion from vector and scalar
32
    ArithQuat(const V& imaginary, T real = 1.0f) : qv(imaginary) , qw(real) {}
33
    ArithQuat(const V& imaginary, T real = 1.0f) : qv(imaginary) , qw(real) {}
33
 
34
 
34
    /// Construct quaternion from four scalars
35
    /// Construct quaternion from four scalars
35
    ArithQuat(T x, T y, T z, T _qw) : qv(x,y,z), qw(_qw) {}
36
    ArithQuat(T x, T y, T z, T _qw) : qv(x,y,z), qw(_qw) {}
36
 
37
 
37
   
38
   
38
    /// Assign values to a quaternion
39
    /// Assign values to a quaternion
39
    void set(const V& imaginary, T real=1.0f)
40
    void set(const V& imaginary, T real=1.0f)
40
    {
41
    {
41
      qv = imaginary;
42
      qv = imaginary;
42
      qw = real;
43
      qw = real;
43
    }
44
    }
44
 
45
 
45
    void set(T x, T y, T z, T _qw) 
46
    void set(T x, T y, T z, T _qw) 
46
    {
47
    {
47
      qv.set(x,y,z);
48
      qv.set(x,y,z);
48
      qw = _qw;
49
      qw = _qw;
49
    }
50
    }
50
 
51
 
51
    /*void set(const Vec4f& v)
52
    /*void set(const Vec4f& v)
52
    {
53
    {
53
      qv.set(v[0], v[1], v[2]);
54
      qv.set(v[0], v[1], v[2]);
54
      qw = v[3];		  
55
      qw = v[3];		  
55
    }*/
56
    }*/
56
 
57
 
57
    /// Get values from a quaternion
58
    /// Get values from a quaternion
58
    void get(T& x, T& y, T& z, T& _qw) const
59
    void get(T& x, T& y, T& z, T& _qw) const
59
    {
60
    {
60
      x  = qv[0];
61
      x  = qv[0];
61
      y  = qv[1];
62
      y  = qv[1];
62
      z  = qv[2];
63
      z  = qv[2];
63
      _qw = qw;
64
      _qw = qw;
64
    }
65
    }
65
 
66
 
66
    /// Get imaginary part of a quaternion
67
    /// Get imaginary part of a quaternion
67
    V get_imaginary_part() const { return qv; }
68
    V get_imaginary_part() const { return qv; }
68
 
69
 
69
    /// Get real part of a quaternion
70
    /// Get real part of a quaternion
70
    T get_real_part() const { return qw; }
71
    T get_real_part() const { return qw; }
71
 
72
 
72
 
73
 
73
 
74
 
74
    /// Obtain angle of rotation and axis
75
    /// Obtain angle of rotation and axis
75
    void get_rot(T& angle, V& v)
76
    void get_rot(T& angle, V& v)
76
    {
77
    {
77
      angle = 2*std::acos(qw);
78
      angle = 2*std::acos(qw);
78
 
79
 
79
      if(angle < TINY) 
80
      if(angle < TINY) 
80
				v = V(static_cast<T>(1.0), static_cast<T>(0.0), static_cast<T>(0.0));
81
				v = V(static_cast<T>(1.0), static_cast<T>(0.0), static_cast<T>(0.0));
81
      else 
82
      else 
82
				v = qv*(static_cast<T>(1.0)/std::sin(angle));
83
				v = qv*(static_cast<T>(1.0)/std::sin(angle));
83
 
84
 
84
      if(angle > M_PI)
85
      if(angle > M_PI)
85
				v = -v;
86
				v = -v;
86
      
87
      
87
      v.normalize();      
88
      v.normalize();      
88
    }
89
    }
89
 
90
 
90
    /// Construct a Quaternion from an angle and axis of rotation.
91
    /// Construct a Quaternion from an angle and axis of rotation.
91
    void make_rot(T angle, const V& v)
92
    void make_rot(T angle, const V& v)
92
    {
93
    {
93
      angle /= static_cast<T>(2.0);
94
      angle /= static_cast<T>(2.0);
94
      qv = CGLA::normalize(v)*std::sin(angle);
95
      qv = CGLA::normalize(v)*std::sin(angle);
95
      qw = std::cos(angle);
96
      qw = std::cos(angle);
96
    }
97
    }
97
 
98
 
98
    /** Construct a Quaternion rotating from the direction given
99
    /** Construct a Quaternion rotating from the direction given
99
	by the first argument to the direction given by the second.*/
100
	by the first argument to the direction given by the second.*/
100
    void make_rot(const V& s,const V& t)
101
    void make_rot(const V& s,const V& t)
101
    {
102
    {
102
      T tmp = std::sqrt(2*(1 + dot(s, t)));
103
      T tmp = std::sqrt(2*(1 + dot(s, t)));
103
      qv = cross(s, t)*(1.0/tmp);
104
      qv = cross(s, t)*(1.0/tmp);
104
      qw = tmp/2.0;    
105
      qw = tmp/2.0;    
105
    }
106
    }
-
 
107
 
-
 
108
	/// Construct a Quaternion from a rotation matrix.
-
 
109
    template <class VT, class MT, unsigned int ROWS>
-
 
110
    void make_rot(ArithSqMatFloat<VT,MT,ROWS>& m)
-
 
111
    {
-
 
112
      assert(ROWS==3 || ROWS==4);
-
 
113
      T trace = m[0][0] + m[1][1] + m[2][2]  + static_cast<T>(1.0);
-
 
114
 
-
 
115
      //If the trace of the matrix is greater than zero, then
-
 
116
      //perform an "instant" calculation.
-
 
117
      if ( trace > TINY ) 
-
 
118
      {
-
 
119
        T S = sqrt(trace) * static_cast<T>(2.0);
-
 
120
        qv = V(m[2][1] - m[1][2], m[0][2] - m[2][0], m[1][0] - m[0][1] );
-
 
121
        qv /= S;
-
 
122
        qw = static_cast<T>(0.25) * S;
-
 
123
      }
-
 
124
      else
-
 
125
      {
-
 
126
        //If the trace of the matrix is equal to zero (or negative...) then identify
-
 
127
        //which major diagonal element has the greatest value.
-
 
128
        //Depending on this, calculate the following:
-
 
129
 
-
 
130
        if ( m[0][0] > m[1][1] && m[0][0] > m[2][2] )  {	// Column 0: 
-
 
131
          T S  = sqrt( static_cast<T>(1.0) + m[0][0] - m[1][1] - m[2][2] ) * static_cast<T>(2.0);
-
 
132
          qv[0] = 0.25f * S;
-
 
133
          qv[1] = (m[1][0] + m[0][1] ) / S;
-
 
134
          qv[2] = (m[0][2] + m[2][0] ) / S;
-
 
135
          qw = (m[2][1] - m[1][3] ) / S;
-
 
136
        } else if ( m[1][1] > m[2][2] ) {			// Column 1: 
-
 
137
          T S  = sqrt( 1.0 + m[1][1] - m[0][0] - m[2][2] ) * 2.0;
-
 
138
          qv[0] = (m[1][0] + m[0][1] ) / S;
-
 
139
          qv[1] = 0.25 * S;
-
 
140
          qv[2] = (m[2][1] + m[1][2] ) / S;
-
 
141
          qw = (m[0][2] - m[2][0] ) / S;
-
 
142
        } else {						// Column 2:
-
 
143
          T S  = sqrt( 1.0 + m[2][2] - m[0][0] - m[1][1] ) * 2.0;
-
 
144
          qv[0] = (m[0][2] + m[2][0] ) / S;
-
 
145
          qv[1] = (m[2][1] + m[1][2] ) / S;
-
 
146
          qv[2] = 0.25 * S;
-
 
147
          qw = (m[1][0] - m[0][1] ) / S;
-
 
148
        }
-
 
149
      }
-
 
150
      //The quaternion is then defined as:
-
 
151
      //  Q = | X Y Z W |
-
 
152
    }
106
 
153
 
107
    //----------------------------------------------------------------------
154
    //----------------------------------------------------------------------
108
    // Binary operators
155
    // Binary operators
109
    //----------------------------------------------------------------------
156
    //----------------------------------------------------------------------
110
    
157
    
111
    bool operator==(const ArithQuat<T,V,Q>& q) const
158
    bool operator==(const ArithQuat<T,V,Q>& q) const
112
    {
159
    {
113
      return qw == q.qw && qv == q.qv;
160
      return qw == q.qw && qv == q.qv;
114
    }
161
    }
115
 
162
 
116
    bool operator!=(const ArithQuat<T,V,Q>& q) const
163
    bool operator!=(const ArithQuat<T,V,Q>& q) const
117
    {
164
    {
118
      return qw != q.qw || qv != q.qv;
165
      return qw != q.qw || qv != q.qv;
119
    }
166
    }
120
 
167
 
121
    /// Multiply two quaternions. (Combine their rotation)
168
    /// Multiply two quaternions. (Combine their rotation)
122
    Q operator*(const ArithQuat<T,V,Q>& q) const
169
    Q operator*(const ArithQuat<T,V,Q>& q) const
123
    {
170
    {
124
      return Q(cross(qv, q.qv) + qv*q.qw + q.qv*qw, 
171
      return Q(cross(qv, q.qv) + qv*q.qw + q.qv*qw, 
125
		         qw*q.qw - dot(qv, q.qv));      
172
		         qw*q.qw - dot(qv, q.qv));      
126
    }
173
    }
127
 
174
 
128
    /// Multiply scalar onto quaternion.
175
    /// Multiply scalar onto quaternion.
129
    Q operator*(T scalar) const
176
    Q operator*(T scalar) const
130
    {
177
    {
131
      return Q(qv*scalar, qw*scalar);
178
      return Q(qv*scalar, qw*scalar);
132
    }
179
    }
133
 
180
 
134
    /// Add two quaternions.
181
    /// Add two quaternions.
135
    Q operator+(const ArithQuat<T,V,Q>& q) const
182
    Q operator+(const ArithQuat<T,V,Q>& q) const
136
    {
183
    {
137
      return Q(qv + q.qv, qw + q.qw);
184
      return Q(qv + q.qv, qw + q.qw);
138
    }
185
    }
139
 
186
 
140
    //----------------------------------------------------------------------
187
    //----------------------------------------------------------------------
141
    // Unary operators
188
    // Unary operators
142
    //----------------------------------------------------------------------
189
    //----------------------------------------------------------------------
143
 
190
 
144
    /// Compute the additive inverse of the quaternion
191
    /// Compute the additive inverse of the quaternion
145
    Q operator-() const { return Q(-qv, -qw); }
192
    Q operator-() const { return Q(-qv, -qw); }
146
 
193
 
147
    /// Compute norm of quaternion
194
    /// Compute norm of quaternion
148
    T norm() const { return dot(qv, qv) + qw*qw; }
195
    T norm() const { return dot(qv, qv) + qw*qw; }
149
 
196
 
150
    /// Return conjugate quaternion
197
    /// Return conjugate quaternion
151
    Q conjugate() const { return Q(-qv, qw); }
198
    Q conjugate() const { return Q(-qv, qw); }
152
 
199
 
153
    /// Compute the multiplicative inverse of the quaternion
200
    /// Compute the multiplicative inverse of the quaternion
154
    Q inverse() const { return Q(conjugate()*(1/norm())); }
201
    Q inverse() const { return Q(conjugate()*(1/norm())); }
155
    
202
    
156
    /// Normalize quaternion.
203
    /// Normalize quaternion.
157
    Q normalize() { return Q((*this)*(1/norm())); }
204
    Q normalize() { return Q((*this)*(1/norm())); }
158
 
205
 
159
    //----------------------------------------------------------------------
206
    //----------------------------------------------------------------------
160
    // Application
207
    // Application
161
    //----------------------------------------------------------------------
208
    //----------------------------------------------------------------------
162
 
209
 
163
    /// Rotate vector according to quaternion
210
    /// Rotate vector according to quaternion
164
    V apply(const V& vec) const 
211
    V apply(const V& vec) const 
165
    {
212
    {
166
      return ((*this)*Q(vec)*inverse()).qv;
213
      return ((*this)*Q(vec)*inverse()).qv;
167
    }
214
    }
168
 
215
 
169
    /// Rotate vector according to unit quaternion
216
    /// Rotate vector according to unit quaternion
170
    V apply_unit(const V& vec) const
217
    V apply_unit(const V& vec) const
171
    {
218
    {
172
	  assert(abs(norm() - 1.0) < SMALL);
219
	  assert(abs(norm() - 1.0) < SMALL);
173
      return ((*this)*Q(vec)*conjugate()).qv;
220
      return ((*this)*Q(vec)*conjugate()).qv;
174
    }
221
    }
175
  };
222
  };
176
 
223
 
177
  template<class T, class V, class Q>
224
  template<class T, class V, class Q>
178
  inline Q operator*(T scalar, const ArithQuat<T,V,Q>& q)
225
  inline Q operator*(T scalar, const ArithQuat<T,V,Q>& q)
179
  {
226
  {
180
    return q*scalar;
227
    return q*scalar;
181
  }
228
  }
182
 
229
 
183
  /** Perform linear interpolation of two quaternions. 
230
  /** Perform linear interpolation of two quaternions. 
184
      The last argument is the parameter used to interpolate
231
      The last argument is the parameter used to interpolate
185
      between the two first. SLERP - invented by Shoemake -
232
      between the two first. SLERP - invented by Shoemake -
186
      is a good way to interpolate because the interpolation
233
      is a good way to interpolate because the interpolation
187
      is performed on the unit sphere. 	
234
      is performed on the unit sphere. 	
188
  */
235
  */
189
	template<class T, class V, class Q>
236
	template<class T, class V, class Q>
190
  inline Q slerp(const ArithQuat<T,V,Q>& q0, const ArithQuat<T,V,Q>& q1, T t)
237
  inline Q slerp(const ArithQuat<T,V,Q>& q0, const ArithQuat<T,V,Q>& q1, T t)
191
  {
238
  {
192
    T angle = std::acos(q0.qv[0]*q1.qv[0] + q0.qv[1]*q1.qv[1] 
239
    T angle = std::acos(q0.qv[0]*q1.qv[0] + q0.qv[1]*q1.qv[1] 
193
			    + q0.qv[2]*q1.qv[2] + q0.qw*q1.qw);
240
			    + q0.qv[2]*q1.qv[2] + q0.qw*q1.qw);
194
    return (q0*std::sin((1 - t)*angle) + q1*std::sin(t*angle))*(1/std::sin(angle));
241
    return (q0*std::sin((1 - t)*angle) + q1*std::sin(t*angle))*(1/std::sin(angle));
195
  }
242
  }
196
 
243
 
197
  /// Print quaternion to stream.
244
  /// Print quaternion to stream.
198
  template<class T, class V, class Q>
245
  template<class T, class V, class Q>
199
  inline std::ostream& operator<<(std::ostream&os, const ArithQuat<T,V,Q>& v)
246
  inline std::ostream& operator<<(std::ostream&os, const ArithQuat<T,V,Q>& v)
200
  {
247
  {
201
    os << "[ ";
248
    os << "[ ";
202
    for(unsigned int i=0;i<3;i++) os << v.qv[i] << " ";
249
    for(unsigned int i=0;i<3;i++) os << v.qv[i] << " ";
203
    os << "~ " << v.qw << " ";
250
    os << "~ " << v.qw << " ";
204
    os << "]";
251
    os << "]";
205
 
252
 
206
    return os;
253
    return os;
207
  }
254
  }
208
}
255
}
209
 
256
 
210
 
257
 
211
 
258
 
212
 
259
 
213
 
260
 
214
 
261
 
215
 
262
 
216
 
263
 
217
 
264
 
218
 
265
 
219
 
266
 
220
 
267
 
221
 
268
 
222
 
269
 
223
 
270
 
224
 
271
 
225
 
272
 
226
#endif // __CGLA_ARITHQUAT_H__
273
#endif // __CGLA_ARITHQUAT_H__
227
 
274