Subversion Repositories gelsvn

Rev

Rev 178 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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