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

Revision 8789, 4.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 #include <assert.h>
36 #include <Math/vjQuat.h>
37
38
39 void vjQuat::makeRot(const vjMatrix& mat)
40 {
41    float tr, s;
42    //static int nxt[3] = {VJ_Y, VJ_Z, VJ_X};
43
44    tr = mat.mat[0][0] + mat.mat[1][1] + mat.mat[2][2];
45
46    // Check the diagonal
47    if (tr > 0.0)
48    {
49       s = sqrt(tr + 1.0);
50       vec[VJ_W] = s/2.0;
51       s = 0.5/s;
52
53       vec[VJ_X] = (mat.mat[1][2] - mat.mat[2][1])*s;
54       vec[VJ_Y] = (mat.mat[2][0] - mat.mat[0][2])*s;
55       vec[VJ_Z] = (mat.mat[0][1] - mat.mat[1][0])*s;
56    }
57    else     // Diagonal is negative
58    {
59       int   i, j, k;
60       int   nxt[3] = {VJ_Y, VJ_Z, VJ_X};
61
62       i = VJ_X;
63
64       if (mat.mat[VJ_Y][VJ_Y] > mat.mat[VJ_X][VJ_X])
65          i = VJ_Y;
66       if (mat.mat[VJ_Z][VJ_Z] > mat.mat[i][i])
67          i = VJ_Z;
68
69       j = nxt[i];
70       k = nxt[j];
71
72       s = sqrt ((mat.mat[i][i] - (mat.mat[j][j] + mat.mat[k][k])) + 1.0);
73
74       vec[i] = s * 0.5;
75
76       if (s != 0.0)
77          s = (0.5 / s);
78
79       vec[VJ_W] = (mat.mat[j][k] - mat.mat[k][j]) * s;
80       vec[j] = (mat.mat[i][j] + mat.mat[j][i]) * s;
81       vec[k] = (mat.mat[i][k] + mat.mat[k][i]) * s;
82    }
83
84 }
85
86 // Multiply the two quaternions
87 // From gdmag
88 void vjQuat::mult(const vjQuat& q1, const vjQuat& q2)
89 {
90    vjQuat tempQuat;
91    tempQuat[VJ_X] = q1[VJ_W]*q2[VJ_X] + q1[VJ_X]*q2[VJ_W] + q1[VJ_Y]*q2[VJ_Z] - q1[VJ_Z]*q2[VJ_Y];
92    tempQuat[VJ_Y] = q1[VJ_W]*q2[VJ_Y] + q1[VJ_Y]*q2[VJ_W] + q1[VJ_Z]*q2[VJ_X] - q1[VJ_X]*q2[VJ_Z];
93    tempQuat[VJ_Z] = q1[VJ_W]*q2[VJ_Z] + q1[VJ_Z]*q2[VJ_W] + q1[VJ_X]*q2[VJ_Y] - q1[VJ_Y]*q2[VJ_X];
94    tempQuat[VJ_W] = q1[VJ_W]*q2[VJ_W] - q1[VJ_X]*q2[VJ_X] - q1[VJ_Y]*q2[VJ_Y] - q1[VJ_Z]*q2[VJ_Z];
95
96    vec[VJ_X] = tempQuat[VJ_X];
97    vec[VJ_Y] = tempQuat[VJ_Y];
98    vec[VJ_Z] = tempQuat[VJ_Z];
99    vec[VJ_W] = tempQuat[VJ_W];
100    this->normalize();               // Make sure it is a unit quaternion
101 }
102
103 // Invert
104 void vjQuat::invert(const vjQuat& q1)
105 {
106    float temp_norm = q1.norm();
107    float inv_norm;
108
109    if (temp_norm >= VJ_QUAT_EPSILON)
110    {
111       inv_norm = 1.0f/temp_norm;
112       vec[VJ_X] = q1.vec[VJ_X]*(-inv_norm);
113       vec[VJ_Y] = q1.vec[VJ_Y]*(-inv_norm);
114       vec[VJ_Z] = q1.vec[VJ_Z]*(-inv_norm);
115       vec[VJ_W] =  q1.vec[VJ_W]*inv_norm;
116    }
117    else
118       set(0.0f, 0.0f, 0.0f, 0.0f);
119 }
120
121 // From Adv Anim and Rendering Tech. Pg 364
122 //
123 void vjQuat::slerp(float t, const vjQuat& p, const vjQuat& q)
124 {
125    vjQuat to;
126    double omega, cosom, sinom, sclp, sclq;
127    //int i;
128
129    // calc cosine
130    cosom = p[VJ_X]*q[VJ_X] + p[VJ_Y]*q[VJ_Y] + p[VJ_Z]*q[VJ_Z]
131            + p[VJ_W]*q[VJ_W];
132
133
134    // adjust signs (if necessary)
135    if ( cosom < 0.0 )
136    {
137       cosom = -cosom;
138       to.vec[0] = -q.vec[0];   // Reverse all signs
139       to.vec[1] = -q.vec[1];
140       to.vec[2] = -q.vec[2];
141       to.vec[3] = -q.vec[3];
142    } else  {
143       to = q;
144    }
145
146    // Calculate coefficients
147
148    if ((1.0 - cosom) > VJ_QUAT_EPSILON)
149    {
150          // Standard case (slerp)
151       omega = acos(cosom);
152       sinom = sin(omega);
153       sclp  = sin((1.0 - t)*omega)/sinom;
154       sclq = sin(t*omega)/sinom;
155    }
156    else
157    {
158          // Very close, do linear interp
159       sclp = 1.0 - t;
160       sclq = t;
161    }
162
163    vec[VJ_X] = sclp*p.vec[VJ_X] + sclq*to.vec[VJ_X];
164    vec[VJ_Y] = sclp*p.vec[VJ_Y] + sclq*to.vec[VJ_Y];
165    vec[VJ_Z] = sclp*p.vec[VJ_Z] + sclq*to.vec[VJ_Z];
166    vec[VJ_W] = sclp*p.vec[VJ_W] + sclq*to.vec[VJ_W];
167
168 }
169
170 void vjQuat::squad(float _t, const vjQuat& _q1, const vjQuat& _q2, const vjQuat& _a, const vjQuat& _b)
171 {
172    assert( false && "not implemented" );
173 }
174
Note: See TracBrowser for help on using the browser.