1 //****************************************************************************//
2 // quaternion.h                                                               //
3 // Copyright (C) 2001, 2002 Bruno 'Beosil' Heidelberger                       //
4 //****************************************************************************//
5 // This library is free software; you can redistribute it and/or modify it    //
6 // under the terms of the GNU Lesser General Public License as published by   //
7 // the Free Software Foundation; either version 2.1 of the License, or (at    //
8 // your option) any later version.                                            //
9 //****************************************************************************//
10 
11 #ifndef CAL_QUATERNION_H
12 #define CAL_QUATERNION_H
13 
14 //****************************************************************************//
15 // Includes                                                                   //
16 //****************************************************************************//
17 
18 #include "cal3d/global.h"
19 #include "cal3d/vector.h"
20 
21 //****************************************************************************//
22 // Forward declarations                                                       //
23 //****************************************************************************//
24 
25 //class CalVector;
26 
27 //****************************************************************************//
28 // Class declaration                                                          //
29 //****************************************************************************//
30 
31  /*****************************************************************************/
32 /** The quaternion class.
33   *****************************************************************************/
34 
35 class CAL3D_API CalQuaternion
36 {
37 	// member variables
38 public:
39 	float x;
40 	float y;
41 	float z;
42 	float w;
43 
44 	// constructors/destructor
45 public:
CalQuaternion()46 	inline CalQuaternion() : x(0.0f), y(0.0f), z(0.0f), w(1.0f){};
CalQuaternion(const CalQuaternion & q)47 	inline CalQuaternion(const CalQuaternion& q): x(q.x), y(q.y), z(q.z), w(q.w) {};
CalQuaternion(float qx,float qy,float qz,float qw)48 	inline CalQuaternion(float qx, float qy, float qz, float qw): x(qx), y(qy), z(qz), w(qw) {};
~CalQuaternion()49 	inline ~CalQuaternion() {};
50 
51 	// member functions
52 public:
53 	inline float& operator[](unsigned int index)
54 	{
55 		return (&x)[index];
56 	}
57 
58 	inline const float& operator[](unsigned int index) const
59 	{
60 		return (&x)[index];
61 	}
62 
63 	inline void operator=(const CalQuaternion& q)
64 		{
65 		x = q.x;
66 		y = q.y;
67 		z = q.z;
68 		w = q.w;
69 	}
70 
71 	inline void operator*=(const CalQuaternion& q)
72 	{
73 		float qx, qy, qz, qw;
74 		qx = x;
75 		qy = y;
76 		qz = z;
77 		qw = w;
78 
79 		x = qw * q.x + qx * q.w + qy * q.z - qz * q.y;
80 		y = qw * q.y - qx * q.z + qy * q.w + qz * q.x;
81 		z = qw * q.z + qx * q.y - qy * q.x + qz * q.w;
82 		w = qw * q.w - qx * q.x - qy * q.y - qz * q.z;
83 	}
84 
85 	inline void operator*=(const CalVector& v)
86 	{
87 		float qx, qy, qz, qw;
88 		qx = x;
89 		qy = y;
90 		qz = z;
91 		qw = w;
92 
93 		x = qw * v.x            + qy * v.z - qz * v.y;
94 		y = qw * v.y - qx * v.z            + qz * v.x;
95 		z = qw * v.z + qx * v.y - qy * v.x;
96 		w =          - qx * v.x - qy * v.y - qz * v.z;
97 	}
98 
99   inline bool operator==(const CalQuaternion& rhs) const
100   {
101     return x == rhs.x &&
102            y == rhs.y &&
103            z == rhs.z &&
104            w == rhs.w;
105   }
106 
107   inline bool operator!=(const CalQuaternion& rhs) const
108   {
109     return !operator==(rhs);
110   }
111 /*
112 	static inline CalQuaternion operator*(const CalQuaternion& q, const CalQuaternion& r)
113 	{
114 		return CalQuaternion(
115 			r.w * q.x + r.x * q.w + r.y * q.z - r.z * q.y,
116 			r.w * q.y - r.x * q.z + r.y * q.w + r.z * q.x,
117 			r.w * q.z + r.x * q.y - r.y * q.x + r.z * q.w,
118 			r.w * q.w - r.x * q.x - r.y * q.y - r.z * q.z
119 			);
120 	}
121 */
blend(float d,const CalQuaternion & q)122 	inline void blend(float d, const CalQuaternion& q)
123 	{
124 		float norm;
125 		norm = x * q.x + y * q.y + z * q.z + w * q.w;
126 
127 		bool bFlip;
128 		bFlip = false;
129 
130 		if(norm < 0.0f)
131 		{
132 			norm = -norm;
133 			bFlip = true;
134 		}
135 
136 		float inv_d;
137 		if(1.0f - norm < 0.000001f)
138 		{
139 			inv_d = 1.0f - d;
140 		}
141 		else
142 		{
143 			float theta;
144 			theta = (float) acos(norm);
145 
146 			float s;
147 			s = (float) (1.0f / sin(theta));
148 
149 			inv_d = (float) sin((1.0f - d) * theta) * s;
150 			d = (float) sin(d * theta) * s;
151 		}
152 
153 		if(bFlip)
154 		{
155 			d = -d;
156 		}
157 
158 		x = inv_d * x + d * q.x;
159 		y = inv_d * y + d * q.y;
160 		z = inv_d * z + d * q.z;
161 		w = inv_d * w + d * q.w;
162 	}
163 
clear()164 	inline void clear()
165 	{
166 		x = 0.0f;
167 		y = 0.0f;
168 		z = 0.0f;
169 		w = 1.0f;
170 	}
conjugate()171 	inline void conjugate()
172 	{
173 		x = -x;
174 		y = -y;
175 		z = -z;
176 	}
177 
invert()178 	inline void invert()
179 	{
180 		conjugate();
181 		const float norm = (x*x) + (y*y) + (z*z) + (w*w);
182 
183 		if (norm == 0.0f) return;
184 
185 		const float inv_norm = 1 / norm;
186 		x *= inv_norm;
187 		y *= inv_norm;
188 		z *= inv_norm;
189 		w *= inv_norm;
190 	}
191 
set(float qx,float qy,float qz,float qw)192 	inline void set(float qx, float qy, float qz, float qw)
193 	{
194 		x = qx;
195 		y = qy;
196 		z = qz;
197 		w = qw;
198 	}
199 
200 	void compress(short &s0, short &s1, short &s2);
201 	void decompress(short &s0, short &s1, short &s2);
202 
203 /*
204 	static inline CalQuaternion shortestArc( const CalVector& from, const CalVector& to )
205 	{
206 		CalVector cross = from % to; //Compute vector cross product
207 		float dot = from * to ;      //Compute dot product
208 
209 		dot = (float) sqrt( 2*(dot+1) ) ; //We will use this equation twice
210 
211 		cross /= dot ; //Get the x, y, z components
212 
213 		//Return with the w component (Note that w is inverted because Cal3D has
214 		// left-handed rotations )
215 		return CalQuaternion( cross[0], cross[1], cross[2], -dot/2 ) ;
216 
217 	}
218 
219   */
220 };
221 
222 
223 static inline CalQuaternion operator*(const CalQuaternion& q, const CalQuaternion& r)
224 {
225 	return CalQuaternion(
226 		r.w * q.x + r.x * q.w + r.y * q.z - r.z * q.y,
227 		r.w * q.y - r.x * q.z + r.y * q.w + r.z * q.x,
228 		r.w * q.z + r.x * q.y - r.y * q.x + r.z * q.w,
229 		r.w * q.w - r.x * q.x - r.y * q.y - r.z * q.z
230 		);
231 }
232 
shortestArc(const CalVector & from,const CalVector & to)233 static inline CalQuaternion shortestArc( const CalVector& from, const CalVector& to )
234 {
235 	CalVector cross = from % to; //Compute vector cross product
236 	float dot = from * to ;      //Compute dot product
237 
238 	dot = (float) sqrt( 2*(dot+1) ) ; //We will use this equation twice
239 
240 	cross /= dot ; //Get the x, y, z components
241 
242 	//Return with the w component (Note that w is inverted because Cal3D has
243 	// left-handed rotations )
244 	return CalQuaternion( cross[0], cross[1], cross[2], -dot/2 ) ;
245 
246 }
247 
248 
249 #endif
250 
251 //****************************************************************************//
252