root/OpenSceneGraph/trunk/include/osg/Quat @ 13041

Revision 13041, 12.9 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSG_QUAT
15#define OSG_QUAT 1
16
17#include <osg/Export>
18#include <osg/Vec3f>
19#include <osg/Vec4f>
20#include <osg/Vec3d>
21#include <osg/Vec4d>
22
23namespace osg {
24
25class Matrixf;
26class Matrixd;
27
28/** A quaternion class. It can be used to represent an orientation in 3D space.*/
29class OSG_EXPORT Quat
30{
31
32    public:
33
34        typedef double value_type;
35
36        value_type  _v[4];    // a four-vector
37
38        inline Quat() { _v[0]=0.0; _v[1]=0.0; _v[2]=0.0; _v[3]=1.0; }
39
40        inline Quat( value_type x, value_type y, value_type z, value_type w )
41        {
42            _v[0]=x;
43            _v[1]=y;
44            _v[2]=z;
45            _v[3]=w;
46        }
47
48        inline Quat( const Vec4f& v )
49        {
50            _v[0]=v.x();
51            _v[1]=v.y();
52            _v[2]=v.z();
53            _v[3]=v.w();
54        }
55
56        inline Quat( const Vec4d& v )
57        {
58            _v[0]=v.x();
59            _v[1]=v.y();
60            _v[2]=v.z();
61            _v[3]=v.w();
62        }
63
64        inline Quat( value_type angle, const Vec3f& axis)
65        {
66            makeRotate(angle,axis);
67        }
68        inline Quat( value_type angle, const Vec3d& axis)
69        {
70            makeRotate(angle,axis);
71        }
72
73        inline Quat( value_type angle1, const Vec3f& axis1,
74                     value_type angle2, const Vec3f& axis2,
75                     value_type angle3, const Vec3f& axis3)
76        {
77            makeRotate(angle1,axis1,angle2,axis2,angle3,axis3);
78        }
79
80        inline Quat( value_type angle1, const Vec3d& axis1,
81                     value_type angle2, const Vec3d& axis2,
82                     value_type angle3, const Vec3d& axis3)
83        {
84            makeRotate(angle1,axis1,angle2,axis2,angle3,axis3);
85        }
86
87        inline Quat& operator = (const Quat& v) { _v[0]=v._v[0];  _v[1]=v._v[1]; _v[2]=v._v[2]; _v[3]=v._v[3]; return *this; }
88
89        inline bool operator == (const Quat& v) const { return _v[0]==v._v[0] && _v[1]==v._v[1] && _v[2]==v._v[2] && _v[3]==v._v[3]; }
90
91        inline bool operator != (const Quat& v) const { return _v[0]!=v._v[0] || _v[1]!=v._v[1] || _v[2]!=v._v[2] || _v[3]!=v._v[3]; }
92
93        inline bool operator <  (const Quat& v) const
94        {
95            if (_v[0]<v._v[0]) return true;
96            else if (_v[0]>v._v[0]) return false;
97            else if (_v[1]<v._v[1]) return true;
98            else if (_v[1]>v._v[1]) return false;
99            else if (_v[2]<v._v[2]) return true;
100            else if (_v[2]>v._v[2]) return false;
101            else return (_v[3]<v._v[3]);
102        }
103
104        /* ----------------------------------
105           Methods to access data members
106        ---------------------------------- */
107
108        inline Vec4d asVec4() const
109        {
110            return Vec4d(_v[0], _v[1], _v[2], _v[3]);
111        }
112
113        inline Vec3d asVec3() const
114        {
115            return Vec3d(_v[0], _v[1], _v[2]);
116        }
117
118        inline void set(value_type x, value_type y, value_type z, value_type w)
119        {
120            _v[0]=x;
121            _v[1]=y;
122            _v[2]=z;
123            _v[3]=w;
124        }
125
126        inline void set(const osg::Vec4f& v)
127        {
128            _v[0]=v.x();
129            _v[1]=v.y();
130            _v[2]=v.z();
131            _v[3]=v.w();
132        }
133
134        inline void set(const osg::Vec4d& v)
135        {
136            _v[0]=v.x();
137            _v[1]=v.y();
138            _v[2]=v.z();
139            _v[3]=v.w();
140        }
141
142        void set(const Matrixf& matrix);
143
144        void set(const Matrixd& matrix);
145
146        void get(Matrixf& matrix) const;
147
148        void get(Matrixd& matrix) const;
149
150
151        inline value_type & operator [] (int i) { return _v[i]; }
152        inline value_type   operator [] (int i) const { return _v[i]; }
153
154        inline value_type & x() { return _v[0]; }
155        inline value_type & y() { return _v[1]; }
156        inline value_type & z() { return _v[2]; }
157        inline value_type & w() { return _v[3]; }
158
159        inline value_type x() const { return _v[0]; }
160        inline value_type y() const { return _v[1]; }
161        inline value_type z() const { return _v[2]; }
162        inline value_type w() const { return _v[3]; }
163
164        /** return true if the Quat represents a zero rotation, and therefore can be ignored in computations.*/
165        bool zeroRotation() const { return _v[0]==0.0 && _v[1]==0.0 && _v[2]==0.0 && _v[3]==1.0; }
166
167
168         /* -------------------------------------------------------------
169                   BASIC ARITHMETIC METHODS
170        Implemented in terms of Vec4s.  Some Vec4 operators, e.g.
171        operator* are not appropriate for quaternions (as
172        mathematical objects) so they are implemented differently.
173        Also define methods for conjugate and the multiplicative inverse.
174        ------------------------------------------------------------- */
175        /// Multiply by scalar
176        inline const Quat operator * (value_type rhs) const
177        {
178            return Quat(_v[0]*rhs, _v[1]*rhs, _v[2]*rhs, _v[3]*rhs);
179        }
180
181        /// Unary multiply by scalar
182        inline Quat& operator *= (value_type rhs)
183        {
184            _v[0]*=rhs;
185            _v[1]*=rhs;
186            _v[2]*=rhs;
187            _v[3]*=rhs;
188            return *this;        // enable nesting
189        }
190
191        /// Binary multiply
192        inline const Quat operator*(const Quat& rhs) const
193        {
194            return Quat( rhs._v[3]*_v[0] + rhs._v[0]*_v[3] + rhs._v[1]*_v[2] - rhs._v[2]*_v[1],
195                 rhs._v[3]*_v[1] - rhs._v[0]*_v[2] + rhs._v[1]*_v[3] + rhs._v[2]*_v[0],
196                 rhs._v[3]*_v[2] + rhs._v[0]*_v[1] - rhs._v[1]*_v[0] + rhs._v[2]*_v[3],
197                 rhs._v[3]*_v[3] - rhs._v[0]*_v[0] - rhs._v[1]*_v[1] - rhs._v[2]*_v[2] );
198        }
199
200        /// Unary multiply
201        inline Quat& operator*=(const Quat& rhs)
202        {
203            value_type x = rhs._v[3]*_v[0] + rhs._v[0]*_v[3] + rhs._v[1]*_v[2] - rhs._v[2]*_v[1];
204            value_type y = rhs._v[3]*_v[1] - rhs._v[0]*_v[2] + rhs._v[1]*_v[3] + rhs._v[2]*_v[0];
205            value_type z = rhs._v[3]*_v[2] + rhs._v[0]*_v[1] - rhs._v[1]*_v[0] + rhs._v[2]*_v[3];
206            _v[3]   = rhs._v[3]*_v[3] - rhs._v[0]*_v[0] - rhs._v[1]*_v[1] - rhs._v[2]*_v[2];
207
208            _v[2] = z;
209            _v[1] = y;
210            _v[0] = x;
211
212            return (*this);            // enable nesting
213        }
214
215        /// Divide by scalar
216        inline Quat operator / (value_type rhs) const
217        {
218            value_type div = 1.0/rhs;
219            return Quat(_v[0]*div, _v[1]*div, _v[2]*div, _v[3]*div);
220        }
221
222        /// Unary divide by scalar
223        inline Quat& operator /= (value_type rhs)
224        {
225            value_type div = 1.0/rhs;
226            _v[0]*=div;
227            _v[1]*=div;
228            _v[2]*=div;
229            _v[3]*=div;
230            return *this;
231        }
232
233        /// Binary divide
234        inline const Quat operator/(const Quat& denom) const
235        {
236            return ( (*this) * denom.inverse() );
237        }
238
239        /// Unary divide
240        inline Quat& operator/=(const Quat& denom)
241        {
242            (*this) = (*this) * denom.inverse();
243            return (*this);            // enable nesting
244        }
245
246        /// Binary addition
247        inline const Quat operator + (const Quat& rhs) const
248        {
249            return Quat(_v[0]+rhs._v[0], _v[1]+rhs._v[1],
250                _v[2]+rhs._v[2], _v[3]+rhs._v[3]);
251        }
252
253        /// Unary addition
254        inline Quat& operator += (const Quat& rhs)
255        {
256            _v[0] += rhs._v[0];
257            _v[1] += rhs._v[1];
258            _v[2] += rhs._v[2];
259            _v[3] += rhs._v[3];
260            return *this;            // enable nesting
261        }
262
263        /// Binary subtraction
264        inline const Quat operator - (const Quat& rhs) const
265        {
266            return Quat(_v[0]-rhs._v[0], _v[1]-rhs._v[1],
267                _v[2]-rhs._v[2], _v[3]-rhs._v[3] );
268        }
269
270        /// Unary subtraction
271        inline Quat& operator -= (const Quat& rhs)
272        {
273            _v[0]-=rhs._v[0];
274            _v[1]-=rhs._v[1];
275            _v[2]-=rhs._v[2];
276            _v[3]-=rhs._v[3];
277            return *this;            // enable nesting
278        }
279
280        /** Negation operator - returns the negative of the quaternion.
281        Basically just calls operator - () on the Vec4 */
282        inline const Quat operator - () const
283        {
284            return Quat (-_v[0], -_v[1], -_v[2], -_v[3]);
285        }
286
287        /// Length of the quaternion = sqrt( vec . vec )
288        value_type length() const
289        {
290            return sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3]);
291        }
292
293        /// Length of the quaternion = vec . vec
294        value_type length2() const
295        {
296            return _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3];
297        }
298
299        /// Conjugate
300        inline Quat conj () const
301        {
302             return Quat( -_v[0], -_v[1], -_v[2], _v[3] );
303        }
304
305        /// Multiplicative inverse method: q^(-1) = q^*/(q.q^*)
306        inline const Quat inverse () const
307        {
308             return conj() / length2();
309         }
310
311      /* --------------------------------------------------------
312               METHODS RELATED TO ROTATIONS
313        Set a quaternion which will perform a rotation of an
314        angle around the axis given by the vector (x,y,z).
315        Should be written to also accept an angle and a Vec3?
316
317        Define Spherical Linear interpolation method also
318
319        Not inlined - see the Quat.cpp file for implementation
320        -------------------------------------------------------- */
321        void makeRotate( value_type  angle,
322                          value_type  x, value_type  y, value_type  z );
323        void makeRotate ( value_type  angle, const Vec3f& vec );
324        void makeRotate ( value_type  angle, const Vec3d& vec );
325
326        void makeRotate ( value_type  angle1, const Vec3f& axis1,
327                          value_type  angle2, const Vec3f& axis2,
328                          value_type  angle3, const Vec3f& axis3);
329        void makeRotate ( value_type  angle1, const Vec3d& axis1,
330                          value_type  angle2, const Vec3d& axis2,
331                          value_type  angle3, const Vec3d& axis3);
332
333        /** Make a rotation Quat which will rotate vec1 to vec2.
334            Generally take a dot product to get the angle between these
335            and then use a cross product to get the rotation axis
336            Watch out for the two special cases when the vectors
337            are co-incident or opposite in direction.*/
338        void makeRotate( const Vec3f& vec1, const Vec3f& vec2 );
339        /** Make a rotation Quat which will rotate vec1 to vec2.
340            Generally take a dot product to get the angle between these
341            and then use a cross product to get the rotation axis
342            Watch out for the two special cases of when the vectors
343            are co-incident or opposite in direction.*/
344        void makeRotate( const Vec3d& vec1, const Vec3d& vec2 );
345
346        void makeRotate_original( const Vec3d& vec1, const Vec3d& vec2 );
347
348        /** Return the angle and vector components represented by the quaternion.*/
349        void getRotate ( value_type & angle, value_type & x, value_type & y, value_type & z ) const;
350
351        /** Return the angle and vector represented by the quaternion.*/
352        void getRotate ( value_type & angle, Vec3f& vec ) const;
353
354        /** Return the angle and vector represented by the quaternion.*/
355        void getRotate ( value_type & angle, Vec3d& vec ) const;
356
357        /** Spherical Linear Interpolation.
358        As t goes from 0 to 1, the Quat object goes from "from" to "to". */
359        void slerp   ( value_type  t, const Quat& from, const Quat& to);
360
361        /** Rotate a vector by this quaternion.*/
362        Vec3f operator* (const Vec3f& v) const
363        {
364            // nVidia SDK implementation
365            Vec3f uv, uuv;
366            Vec3f qvec(_v[0], _v[1], _v[2]);
367            uv = qvec ^ v;
368            uuv = qvec ^ uv;
369            uv *= ( 2.0f * _v[3] );
370            uuv *= 2.0f;
371            return v + uv + uuv;
372        }
373
374        /** Rotate a vector by this quaternion.*/
375        Vec3d operator* (const Vec3d& v) const
376        {
377            // nVidia SDK implementation
378            Vec3d uv, uuv;
379            Vec3d qvec(_v[0], _v[1], _v[2]);
380            uv = qvec ^ v;
381            uuv = qvec ^ uv;
382            uv *= ( 2.0f * _v[3] );
383            uuv *= 2.0f;
384            return v + uv + uuv;
385        }
386
387    protected:
388
389};    // end of class prototype
390
391}    // end of namespace
392
393#endif
Note: See TracBrowser for help on using the browser.