Subversion Repositories gelsvn

Rev

Rev 49 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
48 jrf 1
#ifndef __CGLA_QUATF_H__
2
#define __CGLA_QUATF_H__
3
 
4
#include "Vec3f.h"
5
#include "Vec4f.h"
6
#include "Mat3x3f.h"
7
#include "Mat4x4f.h"
8
 
9
namespace CGLA {
10
 
11
  /** A Quaterinion class. Quaternions are algebraic entities 
12
      useful for rotation. */
13
 
14
  class Quatf
15
  {
16
  public:
17
 
18
    /// Vector part of quaternion
19
    Vec3f qv;
20
 
21
    /// Scalar part of quaternion
22
    float qw;
23
 
24
    /// Construct undefined quaternion
25
#ifndef NDEBUG
26
    Quatf() : qw(CGLA_INIT_VALUE) {}
27
#else
28
    Quatf() {}
29
#endif
30
 
31
    /// Construct quaternion from vector and scalar
32
    Quatf(const Vec3f& imaginary, float real = 1.0f) : qv(imaginary) , qw(real) {}
33
 
34
    /// Construct quaternion from four scalars
35
    Quatf(float x, float y, float z, float _qw) : qv(x,y,z), qw(_qw) {}
36
 
37
    /// Construct quaternion from a 4D vector
38
    explicit Quatf(const Vec4f& v) : qv(v[0], v[1], v[2]), qw(v[3]) {}
39
 
40
    /// Assign values to a quaternion
41
    void set(const Vec3f& imaginary, float real=1.0f)
42
    {
43
      qv = imaginary;
44
      qw = real;
45
    }
46
 
47
    void set(float x, float y, float z, float _qw) 
48
    {
49
      qv.set(x,y,z);
50
      qw = _qw;
51
    }
52
 
53
    void set(const Vec4f& v)
54
    {
55
      qv.set(v[0], v[1], v[2]);
56
      qw = v[3];		  
57
    }
58
 
59
    /// Get values from a quaternion
60
    void get(float& x, float& y, float& z, float& _qw) const
61
    {
62
      x  = qv[0];
63
      y  = qv[1];
64
      z  = qv[2];
65
      _qw = qw;
66
    }
67
 
68
    /// Get imaginary part of a quaternion
69
    Vec3f get_imaginary_part() const { return qv; }
70
 
71
    /// Get real part of a quaternion
72
    float get_real_part() const { return qw; }
73
 
74
    /// Get a 3x3 rotation matrix from a quaternion
75
    Mat3x3f get_mat3x3f() const;
76
 
77
    /// Get a 4x4 rotation matrix from a quaternion
78
    Mat4x4f get_mat4x4f() const;
79
 
80
    /// Obtain angle of rotation and axis
81
    void get_rot(float& angle, Vec3f& vec);
82
 
83
    /// Construct a Quaternion from an angle and axis of rotation.
84
    void make_rot(float angle, const Vec3f&);
85
 
86
    /** Construct a Quaternion rotating from the direction given
87
	by the first argument to the direction given by the second.*/
88
    void make_rot(const Vec3f&,const Vec3f&);
89
 
90
    //----------------------------------------------------------------------
91
    // Binary operators
92
    //----------------------------------------------------------------------
93
 
94
    bool operator==(const Quatf& q) const
95
    {
96
      return qw == q.qw && qv == q.qv;
97
    }
98
 
99
    bool operator!=(const Quatf& q) const
100
    {
101
      return qw != q.qw || qv != q.qv;
102
    }
103
 
104
    /// Multiply two quaternions. (Combine their rotation)
105
    Quatf operator*(const Quatf& q) const
106
    {
107
      return Quatf(cross(qv, q.qv) + qv*q.qw + q.qv*qw, 
108
		         qw*q.qw - dot(qv, q.qv));      
109
    }
110
 
111
    /// Multiply scalar onto quaternion.
112
    Quatf operator*(float scalar) const
113
    {
114
      return Quatf(qv*scalar, qw*scalar);
115
    }
116
 
117
    /// Add two quaternions.
118
    Quatf operator+(const Quatf& q) const
119
    {
120
      return Quatf(qv + q.qv, qw + q.qw);
121
    }
122
 
123
    //----------------------------------------------------------------------
124
    // Unary operators
125
    //----------------------------------------------------------------------
126
 
127
    /// Compute the additive inverse of the quaternion
128
    Quatf operator-() const { return Quatf(-qv, -qw); }
129
 
130
    /// Compute norm of quaternion
131
    float norm() const { return dot(qv, qv) + qw*qw; }
132
 
133
    /// Return conjugate quaternion
134
    Quatf conjugate() const { return Quatf(-qv, qw); }
135
 
136
    /// Compute the multiplicative inverse of the quaternion
137
    Quatf inverse() const { return Quatf(conjugate()*(1/norm())); }
138
 
139
    /// Normalize quaternion.
140
    Quatf normalize() { return Quatf((*this)*(1/norm())); }
141
 
142
    //----------------------------------------------------------------------
143
    // Application
144
    //----------------------------------------------------------------------
145
 
146
    /// Rotate vector according to quaternion
147
    Vec3f apply(const Vec3f& vec) const 
148
    {
149
      return ((*this)*Quatf(vec)*inverse()).qv;
150
    }
151
 
152
    /// Rotate vector according to unit quaternion
153
    Vec3f apply_unit(const Vec3f& vec) const
154
    {
155
      return ((*this)*Quatf(vec)*conjugate()).qv;
156
    }
157
  };
158
 
159
  inline Quatf operator*(float scalar, const Quatf& q)
160
  {
161
    return q*scalar;
162
  }
163
 
164
  /** Perform linear interpolation of two quaternions. 
165
      The last argument is the parameter used to interpolate
166
      between the two first. SLERP - invented by Shoemake -
167
      is a good way to interpolate because the interpolation
168
      is performed on the unit sphere. 	
169
  */
170
  inline Quatf slerp(Quatf q0, Quatf q1, float t);
171
 
172
  /// Create an identity quaternion
173
  inline Quatf identity_Quatf()
174
  {
175
    return Quatf(Vec3f(0.0));
176
  }
177
 
178
  /// Print quaternion to stream.
179
  inline std::ostream& operator<<(std::ostream&os, const Quatf v)
180
  {
181
    os << "[ ";
182
    for(unsigned int i=0;i<3;i++) os << v.qv[i] << " ";
183
    os << "~ " << v.qw << " ";
184
    os << "]";
185
 
186
    return os;
187
  }
188
}
189
#endif