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