root/trunk/dep/include/g3dlite/G3D/Quat.h @ 2

Revision 2, 18.0 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/**
2  @file Quat.h
3 
4  Quaternion
5 
6  @maintainer Morgan McGuire, matrix@graphics3d.com
7 
8  @created 2002-01-23
9  @edited  2006-05-10
10 */
11
12#ifndef G3D_QUAT_H
13#define G3D_QUAT_H
14
15#include "G3D/platform.h"
16#include "G3D/g3dmath.h"
17#include "G3D/Vector3.h"
18#include "G3D/Matrix3.h"
19#include <string>
20
21namespace G3D {
22
23/**
24  Unit quaternions are used in computer graphics to represent
25  rotation about an axis.  Any 3x3 rotation matrix can
26  be stored as a quaternion.
27
28  A quaternion represents the sum of a real scalar and
29  an imaginary vector: ix + jy + kz + w.  A unit quaternion
30  representing a rotation by A about axis v has the form
31  [sin(A/2)*v, cos(A/2)].  For a unit quaternion, q.conj() == q.inverse()
32  is a rotation by -A about v.  -q is the same rotation as q
33  (negate both the axis and angle). 
34 
35  A non-unit quaterion q represents the same rotation as
36  q.unitize() (Dam98 pg 28).
37
38  Although quaternion-vector operations (eg. Quat + Vector3) are
39  well defined, they are not supported by this class because
40  they typically are bugs when they appear in code.
41
42  Do not subclass.
43
44  <B>BETA API -- subject to change</B>
45  @cite Erik B. Dam, Martin Koch, Martin Lillholm, Quaternions, Interpolation and Animation.  Technical Report DIKU-TR-98/5, Department of Computer Science, University of Copenhagen, Denmark.  1998.
46 */
47class Quat {
48private:
49    // Hidden operators
50    bool operator<(const Quat&) const;
51    bool operator>(const Quat&) const;
52    bool operator<=(const Quat&) const;
53    bool operator>=(const Quat&) const;
54
55public:
56
57    /**
58     q = [sin(angle / 2) * axis, cos(angle / 2)]
59   
60     In Watt & Watt's notation, s = w, v = (x, y, z)
61     In the Real-Time Rendering notation, u = (x, y, z), w = w
62     */
63    float x, y, z, w;
64
65    /**
66     Initializes to a zero degree rotation.
67     */
68    inline Quat() : x(0), y(0), z(0), w(1) {}
69
70    Quat(
71        const Matrix3& rot);
72
73    inline Quat(float _x, float _y, float _z, float _w) :
74        x(_x), y(_y), z(_z), w(_w) {}
75
76    /** Defaults to a pure vector quaternion */
77    inline Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) {
78    }
79
80    /**
81     The real part of the quaternion.
82     */
83    inline const float& real() const {
84        return w;
85    }
86
87    inline float& real() {
88        return w;
89    }
90
91    /** Note: two quats can represent the Quat::sameRotation and not be equal. */
92        bool fuzzyEq(const Quat& q) {
93                return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w);
94        }
95
96    /** True if these quaternions represent the same rotation (note that every rotation is
97        represented by two values; q and -q).
98      */
99    bool sameRotation(const Quat& q) {
100        return fuzzyEq(q) || fuzzyEq(-q);
101    }
102
103        inline Quat operator-() const {
104                return Quat(-x, -y, -z, -w);
105        }
106
107    /**
108     Returns the imaginary part (x, y, z)
109     */
110    inline const Vector3& imag() const {
111        return *(reinterpret_cast<const Vector3*>(this));
112    }
113
114    inline Vector3& imag() {
115        return *(reinterpret_cast<Vector3*>(this));
116    }
117
118    /** q = [sin(angle/2)*axis, cos(angle/2)] */
119    static Quat fromAxisAngleRotation(
120        const Vector3&      axis,
121        float               angle);
122
123    /** Returns the axis and angle of rotation represented
124        by this quaternion (i.e. q = [sin(angle/2)*axis, cos(angle/2)]) */
125    void toAxisAngleRotation(
126        Vector3&            axis,
127        double&             angle) const;
128
129    void toAxisAngleRotation(
130        Vector3&            axis,
131        float&              angle) const {
132                double d;
133                toAxisAngleRotation(axis, d);
134                angle = (float)d;
135        }
136
137    Matrix3 toRotationMatrix() const;
138
139    void toRotationMatrix(
140        Matrix3&            rot) const;
141   
142    /**
143     Spherical linear interpolation: linear interpolation along the
144     shortest (3D) great-circle route between two quaternions.
145
146     Note: Correct rotations are expected between 0 and PI in the right order.
147
148     @cite Based on Game Physics -- David Eberly pg 538-540
149     @param threshold Critical angle between between rotations at which
150                the algorithm switches to normalized lerp, which is more
151                        numerically stable in those situations. 0.0 will always slerp.
152     */
153    Quat slerp(
154        const Quat&         other,
155        float               alpha,
156        float               threshold = 0.05f) const;
157
158        /** Normalized linear interpolation of quaternion components. */
159        Quat nlerp(const Quat& other, float alpha) const;
160
161    /**
162     Negates the imaginary part.
163     */
164    inline Quat conj() const {
165        return Quat(-x, -y, -z, w);
166    }
167
168    inline float sum() const {
169        return x + y + z + w;
170    }
171
172    inline float average() const {
173        return sum() / 4.0f;
174    }
175
176    inline Quat operator*(float s) const {
177        return Quat(x * s, y * s, z * s, w * s);
178    }
179
180        /** @cite Based on Watt & Watt, page 360 */
181    friend Quat operator* (float s, const Quat& q);
182
183    inline Quat operator/(float s) const {
184        return Quat(x / s, y / s, z / s, w / s);
185    }
186
187    inline float dot(const Quat& other) const {
188        return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w);
189    }
190
191    /** Note that q<SUP>-1</SUP> = q.conj() for a unit quaternion.
192        @cite Dam99 page 13 */
193    inline Quat inverse() const {
194        return conj() / dot(*this);
195    }
196
197    Quat operator-(const Quat& other) const;
198
199    Quat operator+(const Quat& other) const;
200
201    /**
202     Quaternion multiplication (composition of rotations).
203     Note that this does not commute.
204     */
205    Quat operator*(const Quat& other) const;
206
207    /* (*this) * other.inverse() */
208    Quat operator/(const Quat& other) const {
209        return (*this) * other.inverse();
210    }
211
212
213    /** Is the magnitude nearly 1.0? */
214    inline bool isUnit(float tolerance = 1e-5) const {
215        return abs(dot(*this) - 1.0f) < tolerance;
216    }
217   
218
219    inline float magnitude() const {
220        return sqrtf(dot(*this));
221    }
222
223    inline Quat log() const {
224        if ((x == 0) && (y == 0) && (z == 0)) {
225            if (w > 0) {
226                return Quat(0, 0, 0, ::logf(w));
227            } else if (w < 0) {
228                // Log of a negative number.  Multivalued, any number of the form
229                // (PI * v, ln(-q.w))
230                return Quat((float)G3D_PI, 0, 0, ::logf(-w));
231            } else {
232                 // log of zero!
233                 return Quat((float)nan(), (float)nan(), (float)nan(), (float)nan());
234            }
235        } else {
236            // Partly imaginary.
237            float imagLen = sqrtf(x * x + y * y + z * z);
238            float len = sqrtf(imagLen * imagLen + w * w);
239            float theta = atan2f(imagLen, (float)w);
240            float t = theta / imagLen;
241            return Quat(t * x, t * y, t * z, ::logf(len));
242        }
243    }
244    /** log q = [Av, 0] where q = [sin(A) * v, cos(A)].
245        Only for unit quaternions
246        debugAssertM(isUnit(), "Log only defined for unit quaternions");
247        // Solve for A in q = [sin(A)*v, cos(A)]
248        Vector3 u(x, y, z);
249        double len = u.magnitude();
250
251        if (len == 0.0) {
252            return
253        }
254        double A = atan2((double)w, len);
255        Vector3 v = u / len;
256       
257        return Quat(v * A, 0);
258    }
259    */
260
261    /** exp q = [sin(A) * v, cos(A)] where q = [Av, 0].
262        Only defined for pure-vector quaternions */
263    inline Quat exp() const {
264        debugAssertM(w == 0, "exp only defined for vector quaternions");
265        Vector3 u(x, y, z);
266        float A = u.magnitude();
267        Vector3 v = u / A;
268        return Quat(sinf(A) * v, cosf(A));
269    }
270
271
272    /**
273     Raise this quaternion to a power.  For a rotation, this is
274     the effect of rotating x times as much as the original
275     quaterion.
276
277     Note that q.pow(a).pow(b) == q.pow(a + b)
278     @cite Dam98 pg 21
279     */
280    inline Quat pow(float x) const {
281        return (log() * x).exp();
282    }
283
284
285    /**
286     @deprecated
287     Use toUnit()
288     */
289    inline Quat unitize() const {
290        float mag2 = dot(*this);
291        if (G3D::fuzzyEq(mag2, 1.0f)) {
292            return *this;
293        } else {
294            return *this / sqrtf(mag2);
295        }
296    }
297
298    /**
299     Returns a unit quaterion obtained by dividing through by
300     the magnitude.
301     */
302    inline Quat toUnit() const {
303        return unitize();
304    }
305
306    /**
307     The linear algebra 2-norm, sqrt(q dot q).  This matches
308     the value used in Dam's 1998 tech report but differs from the
309     n(q) value used in Eberly's 1999 paper, which is the square of the
310     norm.
311     */
312    inline float norm() const {
313        return magnitude();
314    }
315
316    // access quaternion as q[0] = q.x, q[1] = q.y, q[2] = q.z, q[3] = q.w
317    //
318    // WARNING.  These member functions rely on
319    // (1) Quat not having virtual functions
320    // (2) the data packed in a 4*sizeof(float) memory block
321    const float& operator[] (int i) const;
322    float& operator[] (int i);
323
324    /** Generate uniform random unit quaternion (i.e. random "direction")
325        @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III.
326   */
327    static Quat unitRandom();
328
329    // 2-char swizzles
330
331    Vector2 xx() const;
332    Vector2 yx() const;
333    Vector2 zx() const;
334    Vector2 wx() const;
335    Vector2 xy() const;
336    Vector2 yy() const;
337    Vector2 zy() const;
338    Vector2 wy() const;
339    Vector2 xz() const;
340    Vector2 yz() const;
341    Vector2 zz() const;
342    Vector2 wz() const;
343    Vector2 xw() const;
344    Vector2 yw() const;
345    Vector2 zw() const;
346    Vector2 ww() const;
347
348    // 3-char swizzles
349
350    Vector3 xxx() const;
351    Vector3 yxx() const;
352    Vector3 zxx() const;
353    Vector3 wxx() const;
354    Vector3 xyx() const;
355    Vector3 yyx() const;
356    Vector3 zyx() const;
357    Vector3 wyx() const;
358    Vector3 xzx() const;
359    Vector3 yzx() const;
360    Vector3 zzx() const;
361    Vector3 wzx() const;
362    Vector3 xwx() const;
363    Vector3 ywx() const;
364    Vector3 zwx() const;
365    Vector3 wwx() const;
366    Vector3 xxy() const;
367    Vector3 yxy() const;
368    Vector3 zxy() const;
369    Vector3 wxy() const;
370    Vector3 xyy() const;
371    Vector3 yyy() const;
372    Vector3 zyy() const;
373    Vector3 wyy() const;
374    Vector3 xzy() const;
375    Vector3 yzy() const;
376    Vector3 zzy() const;
377    Vector3 wzy() const;
378    Vector3 xwy() const;
379    Vector3 ywy() const;
380    Vector3 zwy() const;
381    Vector3 wwy() const;
382    Vector3 xxz() const;
383    Vector3 yxz() const;
384    Vector3 zxz() const;
385    Vector3 wxz() const;
386    Vector3 xyz() const;
387    Vector3 yyz() const;
388    Vector3 zyz() const;
389    Vector3 wyz() const;
390    Vector3 xzz() const;
391    Vector3 yzz() const;
392    Vector3 zzz() const;
393    Vector3 wzz() const;
394    Vector3 xwz() const;
395    Vector3 ywz() const;
396    Vector3 zwz() const;
397    Vector3 wwz() const;
398    Vector3 xxw() const;
399    Vector3 yxw() const;
400    Vector3 zxw() const;
401    Vector3 wxw() const;
402    Vector3 xyw() const;
403    Vector3 yyw() const;
404    Vector3 zyw() const;
405    Vector3 wyw() const;
406    Vector3 xzw() const;
407    Vector3 yzw() const;
408    Vector3 zzw() const;
409    Vector3 wzw() const;
410    Vector3 xww() const;
411    Vector3 yww() const;
412    Vector3 zww() const;
413    Vector3 www() const;
414
415    // 4-char swizzles
416
417    Vector4 xxxx() const;
418    Vector4 yxxx() const;
419    Vector4 zxxx() const;
420    Vector4 wxxx() const;
421    Vector4 xyxx() const;
422    Vector4 yyxx() const;
423    Vector4 zyxx() const;
424    Vector4 wyxx() const;
425    Vector4 xzxx() const;
426    Vector4 yzxx() const;
427    Vector4 zzxx() const;
428    Vector4 wzxx() const;
429    Vector4 xwxx() const;
430    Vector4 ywxx() const;
431    Vector4 zwxx() const;
432    Vector4 wwxx() const;
433    Vector4 xxyx() const;
434    Vector4 yxyx() const;
435    Vector4 zxyx() const;
436    Vector4 wxyx() const;
437    Vector4 xyyx() const;
438    Vector4 yyyx() const;
439    Vector4 zyyx() const;
440    Vector4 wyyx() const;
441    Vector4 xzyx() const;
442    Vector4 yzyx() const;
443    Vector4 zzyx() const;
444    Vector4 wzyx() const;
445    Vector4 xwyx() const;
446    Vector4 ywyx() const;
447    Vector4 zwyx() const;
448    Vector4 wwyx() const;
449    Vector4 xxzx() const;
450    Vector4 yxzx() const;
451    Vector4 zxzx() const;
452    Vector4 wxzx() const;
453    Vector4 xyzx() const;
454    Vector4 yyzx() const;
455    Vector4 zyzx() const;
456    Vector4 wyzx() const;
457    Vector4 xzzx() const;
458    Vector4 yzzx() const;
459    Vector4 zzzx() const;
460    Vector4 wzzx() const;
461    Vector4 xwzx() const;
462    Vector4 ywzx() const;
463    Vector4 zwzx() const;
464    Vector4 wwzx() const;
465    Vector4 xxwx() const;
466    Vector4 yxwx() const;
467    Vector4 zxwx() const;
468    Vector4 wxwx() const;
469    Vector4 xywx() const;
470    Vector4 yywx() const;
471    Vector4 zywx() const;
472    Vector4 wywx() const;
473    Vector4 xzwx() const;
474    Vector4 yzwx() const;
475    Vector4 zzwx() const;
476    Vector4 wzwx() const;
477    Vector4 xwwx() const;
478    Vector4 ywwx() const;
479    Vector4 zwwx() const;
480    Vector4 wwwx() const;
481    Vector4 xxxy() const;
482    Vector4 yxxy() const;
483    Vector4 zxxy() const;
484    Vector4 wxxy() const;
485    Vector4 xyxy() const;
486    Vector4 yyxy() const;
487    Vector4 zyxy() const;
488    Vector4 wyxy() const;
489    Vector4 xzxy() const;
490    Vector4 yzxy() const;
491    Vector4 zzxy() const;
492    Vector4 wzxy() const;
493    Vector4 xwxy() const;
494    Vector4 ywxy() const;
495    Vector4 zwxy() const;
496    Vector4 wwxy() const;
497    Vector4 xxyy() const;
498    Vector4 yxyy() const;
499    Vector4 zxyy() const;
500    Vector4 wxyy() const;
501    Vector4 xyyy() const;
502    Vector4 yyyy() const;
503    Vector4 zyyy() const;
504    Vector4 wyyy() const;
505    Vector4 xzyy() const;
506    Vector4 yzyy() const;
507    Vector4 zzyy() const;
508    Vector4 wzyy() const;
509    Vector4 xwyy() const;
510    Vector4 ywyy() const;
511    Vector4 zwyy() const;
512    Vector4 wwyy() const;
513    Vector4 xxzy() const;
514    Vector4 yxzy() const;
515    Vector4 zxzy() const;
516    Vector4 wxzy() const;
517    Vector4 xyzy() const;
518    Vector4 yyzy() const;
519    Vector4 zyzy() const;
520    Vector4 wyzy() const;
521    Vector4 xzzy() const;
522    Vector4 yzzy() const;
523    Vector4 zzzy() const;
524    Vector4 wzzy() const;
525    Vector4 xwzy() const;
526    Vector4 ywzy() const;
527    Vector4 zwzy() const;
528    Vector4 wwzy() const;
529    Vector4 xxwy() const;
530    Vector4 yxwy() const;
531    Vector4 zxwy() const;
532    Vector4 wxwy() const;
533    Vector4 xywy() const;
534    Vector4 yywy() const;
535    Vector4 zywy() const;
536    Vector4 wywy() const;
537    Vector4 xzwy() const;
538    Vector4 yzwy() const;
539    Vector4 zzwy() const;
540    Vector4 wzwy() const;
541    Vector4 xwwy() const;
542    Vector4 ywwy() const;
543    Vector4 zwwy() const;
544    Vector4 wwwy() const;
545    Vector4 xxxz() const;
546    Vector4 yxxz() const;
547    Vector4 zxxz() const;
548    Vector4 wxxz() const;
549    Vector4 xyxz() const;
550    Vector4 yyxz() const;
551    Vector4 zyxz() const;
552    Vector4 wyxz() const;
553    Vector4 xzxz() const;
554    Vector4 yzxz() const;
555    Vector4 zzxz() const;
556    Vector4 wzxz() const;
557    Vector4 xwxz() const;
558    Vector4 ywxz() const;
559    Vector4 zwxz() const;
560    Vector4 wwxz() const;
561    Vector4 xxyz() const;
562    Vector4 yxyz() const;
563    Vector4 zxyz() const;
564    Vector4 wxyz() const;
565    Vector4 xyyz() const;
566    Vector4 yyyz() const;
567    Vector4 zyyz() const;
568    Vector4 wyyz() const;
569    Vector4 xzyz() const;
570    Vector4 yzyz() const;
571    Vector4 zzyz() const;
572    Vector4 wzyz() const;
573    Vector4 xwyz() const;
574    Vector4 ywyz() const;
575    Vector4 zwyz() const;
576    Vector4 wwyz() const;
577    Vector4 xxzz() const;
578    Vector4 yxzz() const;
579    Vector4 zxzz() const;
580    Vector4 wxzz() const;
581    Vector4 xyzz() const;
582    Vector4 yyzz() const;
583    Vector4 zyzz() const;
584    Vector4 wyzz() const;
585    Vector4 xzzz() const;
586    Vector4 yzzz() const;
587    Vector4 zzzz() const;
588    Vector4 wzzz() const;
589    Vector4 xwzz() const;
590    Vector4 ywzz() const;
591    Vector4 zwzz() const;
592    Vector4 wwzz() const;
593    Vector4 xxwz() const;
594    Vector4 yxwz() const;
595    Vector4 zxwz() const;
596    Vector4 wxwz() const;
597    Vector4 xywz() const;
598    Vector4 yywz() const;
599    Vector4 zywz() const;
600    Vector4 wywz() const;
601    Vector4 xzwz() const;
602    Vector4 yzwz() const;
603    Vector4 zzwz() const;
604    Vector4 wzwz() const;
605    Vector4 xwwz() const;
606    Vector4 ywwz() const;
607    Vector4 zwwz() const;
608    Vector4 wwwz() const;
609    Vector4 xxxw() const;
610    Vector4 yxxw() const;
611    Vector4 zxxw() const;
612    Vector4 wxxw() const;
613    Vector4 xyxw() const;
614    Vector4 yyxw() const;
615    Vector4 zyxw() const;
616    Vector4 wyxw() const;
617    Vector4 xzxw() const;
618    Vector4 yzxw() const;
619    Vector4 zzxw() const;
620    Vector4 wzxw() const;
621    Vector4 xwxw() const;
622    Vector4 ywxw() const;
623    Vector4 zwxw() const;
624    Vector4 wwxw() const;
625    Vector4 xxyw() const;
626    Vector4 yxyw() const;
627    Vector4 zxyw() const;
628    Vector4 wxyw() const;
629    Vector4 xyyw() const;
630    Vector4 yyyw() const;
631    Vector4 zyyw() const;
632    Vector4 wyyw() const;
633    Vector4 xzyw() const;
634    Vector4 yzyw() const;
635    Vector4 zzyw() const;
636    Vector4 wzyw() const;
637    Vector4 xwyw() const;
638    Vector4 ywyw() const;
639    Vector4 zwyw() const;
640    Vector4 wwyw() const;
641    Vector4 xxzw() const;
642    Vector4 yxzw() const;
643    Vector4 zxzw() const;
644    Vector4 wxzw() const;
645    Vector4 xyzw() const;
646    Vector4 yyzw() const;
647    Vector4 zyzw() const;
648    Vector4 wyzw() const;
649    Vector4 xzzw() const;
650    Vector4 yzzw() const;
651    Vector4 zzzw() const;
652    Vector4 wzzw() const;
653    Vector4 xwzw() const;
654    Vector4 ywzw() const;
655    Vector4 zwzw() const;
656    Vector4 wwzw() const;
657    Vector4 xxww() const;
658    Vector4 yxww() const;
659    Vector4 zxww() const;
660    Vector4 wxww() const;
661    Vector4 xyww() const;
662    Vector4 yyww() const;
663    Vector4 zyww() const;
664    Vector4 wyww() const;
665    Vector4 xzww() const;
666    Vector4 yzww() const;
667    Vector4 zzww() const;
668    Vector4 wzww() const;
669    Vector4 xwww() const;
670    Vector4 ywww() const;
671    Vector4 zwww() const;
672    Vector4 wwww() const;
673};
674
675inline Quat exp(const Quat& q) {
676    return q.exp();
677}
678
679inline Quat log(const Quat& q) {
680    return q.log();
681}
682
683inline G3D::Quat operator*(double s, const G3D::Quat& q) {
684    return q * (float)s;
685}
686
687inline G3D::Quat operator*(float s, const G3D::Quat& q) {
688    return q * s;
689}
690
691} // Namespace G3D
692
693// Outside the namespace to avoid overloading confusion for C++
694inline G3D::Quat pow(const G3D::Quat& q, double x) {
695    return q.pow((float)x);
696}
697
698
699
700#include "Quat.inl"
701
702#endif
Note: See TracBrowser for help on using the browser.