1 /*******************************************************************************
2 Copyright 2008 Ian Wadham <ianw2@optusnet.com.au>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *******************************************************************************/
20 A little library to do quaternion arithmetic. Adapted from C to C++.
21 Acknowledgements and thanks to John Darrington and the Gnubik package.
24 #include "quaternion.h"
30 Quaternion::Quaternion ()
32 quaternionSetIdentity();
36 Quaternion::Quaternion (double rPart
, double iPart
, double jPart
, double kPart
)
45 void Quaternion::quaternionSetIdentity ()
54 void Quaternion::quaternionAddRotation
55 (const double axis
[], const double degrees
)
57 // If the axis-vector and quaternion are both normalised,
58 // then the new quaternion will also be normalised.
61 double radians
= degrees
* M_PI
/ 180.0;
62 double s
= sin (radians
/ 2.0);
64 q
.w
= cos (radians
/ 2.0);
69 quaternionPreMultiply (this, &q
);
73 void Quaternion::quaternionPreMultiply
74 (Quaternion
* q1
, const Quaternion
* q2
) const
87 double cross_product
[3];
93 dot_product
= x1
*x2
+ y1
*y2
+ z1
*z2
;
95 printf("Dot product is %f\n",dot_product);
97 cross_product
[0] = y1
*z2
- z1
*y2
;
98 cross_product
[1] = z1
*x2
- x1
*z2
;
99 cross_product
[2] = x1
*y2
- y1
*x2
;
101 printf("Cross product is %f, %f, %f\n",cross_product[0],
105 q1
->w
= s1
*s2
- dot_product
;
106 q1
->x
= s1
*x2
+ s2
*x1
+ cross_product
[0];
107 q1
->y
= s1
*y2
+ s2
*y1
+ cross_product
[1];
108 q1
->z
= s1
*z2
+ s2
*z1
+ cross_product
[2];
112 void Quaternion::quaternionToMatrix (Matrix M
) const
127 int dim
= DIMENSIONS
;
130 M
[0 + dim
* 0] = ww
+ xx
- yy
- zz
; // If q is normalised, 1 - 2*y2 - 2*z2.
131 M
[1 + dim
* 1] = ww
- xx
+ yy
- zz
; // etc.
132 M
[2 + dim
* 2] = ww
- xx
- yy
+ zz
; // etc.
133 M
[3 + dim
* 3] = ww
+ xx
+ yy
+ zz
; // If q is normalised, this is 1.0.
136 M
[0 + dim
* 3] = 0.0;
137 M
[1 + dim
* 3] = 0.0;
138 M
[2 + dim
* 3] = 0.0;
141 M
[3 + dim
* 0] = 0.0;
142 M
[3 + dim
* 1] = 0.0;
143 M
[3 + dim
* 2] = 0.0;
146 M
[0 + dim
* 1] = 2.0 * (xy
+ wz
);
147 M
[0 + dim
* 2] = 2.0 * (zx
- wy
);
148 M
[1 + dim
* 2] = 2.0 * (yz
+ wx
);
150 M
[1 + dim
* 0] = 2.0 * (xy
- wz
);
151 M
[2 + dim
* 0] = 2.0 * (zx
+ wy
);
152 M
[2 + dim
* 1] = 2.0 * (yz
- wx
);
156 void Quaternion::quaternionInvert()
164 void Quaternion::quaternionRotateVector (double axis
[3]) const
166 // Make a copy of the quaternion ("this") that will rotate the vector.
167 Quaternion
q (w
, x
, y
, z
);
169 // Convert the vector to a quaternion.
170 Quaternion
v (0.0, axis
[0], axis
[1], axis
[2]);
172 // Get the inverse of "this" quaternion.
173 Quaternion
q1 (w
, -x
, -y
, -z
);
175 // Multiply the three quaternions together: q*v*q1.
176 quaternionPreMultiply (&q1
, &v
);
177 quaternionPreMultiply (&q1
, &q
);
179 // Return the rotated vector.
186 void Quaternion::quaternionPrint() const
188 printf ("Quaternion (%6.3f, %6.3f, %6.3f, %6.3f)\n", w
, x
, y
, z
);
189 Quaternion
p (w
, x
, y
, z
);
190 double mod
= sqrt (p
.w
* p
.w
+ p
.x
* p
.x
+ p
.y
* p
.y
+ p
.z
* p
.z
);
195 double rad
= acos (p
.w
);
196 if (fabs (rad
) >= 0.0001) {
197 double s
= sin (rad
);
198 printf ("Angle %8.3f, axis (%6.3f, %6.3f, %6.3f)\n",
199 2.0 * rad
* 180.0 / M_PI
, p
.x
/s
, p
.y
/s
, p
.z
/s
);
202 printf ("Angle %8.3f, axis (%6.3f, %6.3f, %6.3f)\n",