root/juggler/branches/1.0/Math/vjQuat.h

Revision 8789, 6.7 kB (checked in by patrickh, 7 years ago)

Copyright update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
2  *
3  * VR Juggler is (C) Copyright 1998, 1999, 2000, 2001, 2002
4  *   by Iowa State University
5  *
6  * Original Authors:
7  *   Allen Bierbaum, Christopher Just,
8  *   Patrick Hartling, Kevin Meinert,
9  *   Carolina Cruz-Neira, Albert Baker
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  *
26  * -----------------------------------------------------------------
27  * File:          $RCSfile$
28  * Date modified: $Date$
29  * Version:       $Revision$
30  * -----------------------------------------------------------------
31  *
32  *************** <auto-copyright.pl END do not edit this line> ***************/
33
34
35 #ifndef _VJ_QUAT_H_
36 #define _VJ_QUAT_H_
37
38 #include <math.h>
39
40 #include <Math/vjVec4.h>
41 #include <Math/vjVec3.h>
42 #include <Math/vjMatrix.h>
43
44 #define VJ_QUAT_EPSILON     0.00001f
45
46 // ----------------------------------------------------------------------------
47 //: Class to encapsulate quaternion behaviors.
48 //
49 // Note: The code for most of these routines was borrowed from the the folling
50 // sources.
51 //
52 //    Game Developer Magazine: Feb 98, pg.34-42                   <br>
53 //    Advanced Animation and Rendering Techniques: pp363-365      <br>
54 //    Quaternion Calculus for Animation,  Ken Shoemake SIGGRAPH course notes 1989  <br>
55 //    Animating Rotation with Quaternion Curves,  Ken Shoemake <br>
56 //       SIGGRAPH Proceedings Vol 19, Number 3, 1985           <br>
57 //-----------------------------------------------------------------------------
58 //!PUBLIC_API:
59 class vjQuat : public vjVec4
60 {
61 public:
62    vjQuat()
63    {}
64
65    //: Construct Quat from 4 floats
66    vjQuat( const float x,
67            const float y,
68            const float z,
69            const float w)
70    {
71       vec[VJ_X] = x;
72       vec[VJ_Y] = y;
73       vec[VJ_Z] = z;
74       vec[VJ_W] = w;
75    }
76    
77    //: Construct quat from matrix
78    void makeRot( const vjMatrix& mat );
79
80    //: get the quat's twist (radians) and vector
81    void getRot( float& rad, float& x, float& y, float& z ) const
82    {
83       vjQuat quat = *this;
84      
85       // make sure we don't get a NaN result from acos...
86       if (fabsf( quat.vec[VJ_W] ) > 1.0f)
87       {
88          quat.normalize();
89       }
90
91       float halfrad = acosf(quat.vec[VJ_W]);
92       float sin_halfrad = sinf( halfrad );
93       float oneOverSinHalfRad;
94      
95       if (sin_halfrad != 0.0f)
96       {
97          oneOverSinHalfRad = 1.0f / sin_halfrad;
98       }
99      
100       // avoid NAN
101       // if rad == 0, then the vector is undefined anyway,
102       // since there is no twist, there is no need for a vector (set to 0)
103       else
104       {
105          oneOverSinHalfRad = 0.0f;
106       }
107      
108            rad = halfrad * 2.0f;
109       vjVec3 t;
110            t[0] = quat.vec[VJ_X] * ( oneOverSinHalfRad );
111       t[1] = quat.vec[VJ_Y] * ( oneOverSinHalfRad );
112                 t[2] = quat.vec[VJ_Z] * ( oneOverSinHalfRad );
113       //t.normalize();
114       x = t[0];
115       y = t[1];
116       z = t[2];
117      
118       // avoid 0,0,0,0 when deg is 0.  make it 0,1,0,0
119       if (oneOverSinHalfRad == 0.0f)
120       {
121          x = 1.0f;
122       }
123    }
124
125    //: make a quat from a twist (radians) about a vector (normalized)
126    void makeRot( const float& rad, const float& x, const float& y, const float& z )
127    {
128       float halfRad = rad * 0.5f;
129            float sinHalfRad = sinf( halfRad );
130            vjVec3 vecNormalized;
131          
132       if (rad == 0.0f || (x == 0.0f && y == 0.0f && z == 0.0f))
133       {
134          vecNormalized.set( 1.0f, 0.0f, 0.0f );
135       }
136       else
137       {
138          vecNormalized.set( x, y, z );
139               vecNormalized.normalize();
140       }
141            vec[VJ_W] = cosf( halfRad );
142            vec[VJ_X] = sinHalfRad * vecNormalized[0];
143            vec[VJ_Y] = sinHalfRad * vecNormalized[1];
144            vec[VJ_Z] = sinHalfRad * vecNormalized[2];
145            this->normalizeFast();
146    }
147  
148    //: set to conj of quat
149    void conj(const vjQuat& quat)
150    {
151       *this = quat;
152       vec[VJ_X] = -quat.vec[VJ_X];
153       vec[VJ_Y] = -quat.vec[VJ_Y];
154       vec[VJ_Z] = -quat.vec[VJ_Z];
155    }
156
157    float norm() const
158    {
159       return ((vec[0]*vec[0])+(vec[1]*vec[1])+(vec[2]*vec[2])+(vec[3]*vec[3]));
160    }
161
162    // make a unit quat (normalize it)
163    void normalizeFast()
164    {
165       float n = 1 / this->norm();
166       vec[VJ_W] = vec[VJ_W] * n;
167       vec[VJ_X] = vec[VJ_X] * n;
168       vec[VJ_Y] = vec[VJ_Y] * n;
169       vec[VJ_Z] = vec[VJ_Z] * n;
170    }
171        
172
173 public:
174    //: Multiply two quaternions
175    //!POST: this' = q1 * q2
176    void mult(const vjQuat& q1, const vjQuat& q2);
177
178    // quat = q1/q2
179    void div(const vjQuat& q1, const vjQuat& q2)
180    {
181       vjQuat r, s;
182       vjQuat inv_denom;
183       inv_denom.invert(q2);
184
185       r.mult(q1, inv_denom);
186       s.mult(inv_denom, inv_denom);
187
188       vec[VJ_X] = r.vec[VJ_X] / s.vec[VJ_W];
189       vec[VJ_Y] = r.vec[VJ_Y] / s.vec[VJ_W];
190       vec[VJ_Z] = r.vec[VJ_Z] / s.vec[VJ_W];
191       vec[VJ_W] = r.vec[VJ_W] / s.vec[VJ_W];
192    }
193
194    // quat = inv(q1)
195    void invert(const vjQuat& q1);
196
197    //void exp(const vjQuat& _q);
198    //void log(const vjQuat& _q);
199
200    void slerp(float _t, const vjQuat& _q1, const vjQuat& _q2);
201    
202    // not implemented
203    void squad(float _t, const vjQuat& _q1, const vjQuat& _q2, const vjQuat& _a, const vjQuat& _b);
204
205    //void meanTangent(const vjQuat& _q1, const vjQuat& _q2, const vjQuat& _q3);
206
207 public:
208    // vjQuat operators
209    vjQuat operator *(const vjQuat&  _m) const {
210       vjQuat dst; dst.mult(*this, _m); return dst;
211    }
212
213    vjQuat operator /(const vjQuat&  _m) const {
214       vjQuat dst; dst.div(*this, _m); return dst;
215    }
216
217 public:
218    // Assignment operators
219    vjQuat&  operator *=(const vjQuat& _q) {
220       this->mult(*this, _q); return *this;
221    }
222    vjQuat&  operator /=(const vjQuat& _q) {
223       this->div(*this, _q); return *this;
224    }
225    
226    inline std::ostream& outStream( std::ostream& out )
227    {
228            float rad;
229            float x, y, z;
230            this->getRot( rad, x, y, z );
231
232            //out << vec[VJ_W] << ", " << vec[VJ_X] << ", " << vec[VJ_Y] << ", " << vec[VJ_Z];
233            out << VJ_RAD2DEG( rad ) << " deg, " << x << ", " << y << ", " << z;
234            return out;
235    }
236    
237    inline friend std::ostream& operator<<( std::ostream& out, vjQuat& q )
238    {
239            q.outStream( out );
240            return out;
241    }
242 };
243
244 #endif
Note: See TracBrowser for help on using the browser.