root/juggler/tags/1.0.5/Math/vjQuat.cpp

Revision 7539, 4.7 kB (checked in by anonymous, 7 years ago)

This commit was manufactured by cvs2svn to create tag
'RELENG_1_0_5_RELEASE'.

  • 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 by Iowa State University
4  *
5  * Original Authors:
6  *   Allen Bierbaum, Christopher Just,
7  *   Patrick Hartling, Kevin Meinert,
8  *   Carolina Cruz-Neira, Albert Baker
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  *
25  * -----------------------------------------------------------------
26  * File:          $RCSfile$
27  * Date modified: $Date$
28  * Version:       $Revision$
29  * -----------------------------------------------------------------
30  *
31  *************** <auto-copyright.pl END do not edit this line> ***************/
32
33
34 #include <assert.h>
35 #include <Math/vjQuat.h>
36
37
38 void vjQuat::makeRot(const vjMatrix& mat)
39 {
40    float tr, s;
41    //static int nxt[3] = {VJ_Y, VJ_Z, VJ_X};
42
43    tr = mat.mat[0][0] + mat.mat[1][1] + mat.mat[2][2];
44
45    // Check the diagonal
46    if (tr > 0.0)
47    {
48       s = sqrt(tr + 1.0);
49       vec[VJ_W] = s/2.0;
50       s = 0.5/s;
51
52       vec[VJ_X] = (mat.mat[1][2] - mat.mat[2][1])*s;
53       vec[VJ_Y] = (mat.mat[2][0] - mat.mat[0][2])*s;
54       vec[VJ_Z] = (mat.mat[0][1] - mat.mat[1][0])*s;
55    }
56    else     // Diagonal is negative
57    {
58       int   i, j, k;
59       int   nxt[3] = {VJ_Y, VJ_Z, VJ_X};
60
61       i = VJ_X;
62
63       if (mat.mat[VJ_Y][VJ_Y] > mat.mat[VJ_X][VJ_X])
64          i = VJ_Y;
65       if (mat.mat[VJ_Z][VJ_Z] > mat.mat[i][i])
66          i = VJ_Z;
67
68       j = nxt[i];
69       k = nxt[j];
70
71       s = sqrt ((mat.mat[i][i] - (mat.mat[j][j] + mat.mat[k][k])) + 1.0);
72
73       vec[i] = s * 0.5;
74
75       if (s != 0.0)
76          s = (0.5 / s);
77
78       vec[VJ_W] = (mat.mat[j][k] - mat.mat[k][j]) * s;
79       vec[j] = (mat.mat[i][j] + mat.mat[j][i]) * s;
80       vec[k] = (mat.mat[i][k] + mat.mat[k][i]) * s;
81    }
82
83 }
84
85 // Multiply the two quaternions
86 // From gdmag
87 void vjQuat::mult(const vjQuat& q1, const vjQuat& q2)
88 {
89    vjQuat tempQuat;
90    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];
91    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];
92    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];
93    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];
94
95    vec[VJ_X] = tempQuat[VJ_X];
96    vec[VJ_Y] = tempQuat[VJ_Y];
97    vec[VJ_Z] = tempQuat[VJ_Z];
98    vec[VJ_W] = tempQuat[VJ_W];
99    this->normalize();               // Make sure it is a unit quaternion
100 }
101
102 // Invert
103 void vjQuat::invert(const vjQuat& q1)
104 {
105    float temp_norm = q1.norm();
106    float inv_norm;
107
108    if (temp_norm >= VJ_QUAT_EPSILON)
109    {
110       inv_norm = 1.0f/temp_norm;
111       vec[VJ_X] = q1.vec[VJ_X]*(-inv_norm);
112       vec[VJ_Y] = q1.vec[VJ_Y]*(-inv_norm);
113       vec[VJ_Z] = q1.vec[VJ_Z]*(-inv_norm);
114       vec[VJ_W] =  q1.vec[VJ_W]*inv_norm;
115    }
116    else
117       set(0.0f, 0.0f, 0.0f, 0.0f);
118 }
119
120 // From Adv Anim and Rendering Tech. Pg 364
121 //
122 void vjQuat::slerp(float t, const vjQuat& p, const vjQuat& q)
123 {
124    vjQuat to;
125    double omega, cosom, sinom, sclp, sclq;
126    //int i;
127
128    // calc cosine
129    cosom = p[VJ_X]*q[VJ_X] + p[VJ_Y]*q[VJ_Y] + p[VJ_Z]*q[VJ_Z]
130            + p[VJ_W]*q[VJ_W];
131
132
133    // adjust signs (if necessary)
134    if ( cosom < 0.0 )
135    {
136       cosom = -cosom;
137       to.vec[0] = -q.vec[0];   // Reverse all signs
138       to.vec[1] = -q.vec[1];
139       to.vec[2] = -q.vec[2];
140       to.vec[3] = -q.vec[3];
141    } else  {
142       to = q;
143    }
144
145    // Calculate coefficients
146
147    if ((1.0 - cosom) > VJ_QUAT_EPSILON)
148    {
149          // Standard case (slerp)
150       omega = acos(cosom);
151       sinom = sin(omega);
152       sclp  = sin((1.0 - t)*omega)/sinom;
153       sclq = sin(t*omega)/sinom;
154    }
155    else
156    {
157          // Very close, do linear interp
158       sclp = 1.0 - t;
159       sclq = t;
160    }
161
162    vec[VJ_X] = sclp*p.vec[VJ_X] + sclq*to.vec[VJ_X];
163    vec[VJ_Y] = sclp*p.vec[VJ_Y] + sclq*to.vec[VJ_Y];
164    vec[VJ_Z] = sclp*p.vec[VJ_Z] + sclq*to.vec[VJ_Z];
165    vec[VJ_W] = sclp*p.vec[VJ_W] + sclq*to.vec[VJ_W];
166
167 }
168
169 void vjQuat::squad(float _t, const vjQuat& _q1, const vjQuat& _q2, const vjQuat& _a, const vjQuat& _b)
170 {
171    assert( false && "not implemented" );
172 }
173
Note: See TracBrowser for help on using the browser.