Subversion Repositories gelsvn

Rev

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