1 #ifndef CMU462_QUATERNION_H
2 #define CMU462_QUATERNION_H
12 class Quaternion :
public Vector4D {
19 Quaternion( ) :
Vector4D( 0.0, 0.0, 0.0, 1.0 ) { }
24 Quaternion(
const Vector3D& v,
double w) :
Vector4D(v.x, v.y, v.z, w) { }
26 Quaternion(
const Vector4D& v) :
Vector4D(v.x, v.y, v.z, v.w) { }
28 Quaternion(
double x,
double y,
double z,
double w) :
Vector4D(x, y, z, w) { }
34 void from_axis_angle(
const Vector3D& axis,
double radians) {
36 const Vector3D& nAxis = axis.unit();
37 double sinTheta = sin(radians);
38 x = sinTheta * nAxis.x;
39 y = sinTheta * nAxis.y;
40 z = sinTheta * nAxis.z;
45 Vector3D complex()
const {
return Vector3D(x, y, z); }
46 void setComplex(
const Vector3D& c)
53 double real()
const {
return w; }
54 void setReal(
double r) { w = r; }
56 Quaternion conjugate(
void)
const
58 return Quaternion(-complex(), real());
71 Quaternion inverse(
void)
const
73 return conjugate() /
norm();
85 Quaternion product(
const Quaternion& rhs)
const {
86 return Quaternion(y*rhs.z - z*rhs.y + x*rhs.w + w*rhs.x,
87 z*rhs.x - x*rhs.z + y*rhs.w + w*rhs.y,
88 x*rhs.y - y*rhs.x + z*rhs.w + w*rhs.z,
89 w*rhs.w - x*rhs.x - y*rhs.y - z*rhs.z);
108 Quaternion operator*(
const Quaternion& rhs)
const {
123 Matrix4x4 matrix()
const {
147 Matrix4x4 rightMatrix()
const {
173 Matrix3x3 rotationMatrix()
const {
175 1-2*y*y-2*z*z, 2*x*y - 2*z*w, 2*x*z + 2*y*w,
176 2*x*y + 2*z*w, 1-2*x*x-2*z*z, 2*y*z - 2*x*w,
177 2*x*z - 2*y*w, 2*y*z + 2*x*w, 1-2*x*x-2*y*y
188 Vector3D scaledAxis(
void)
const{
190 Quaternion q1 = (Quaternion)
unit();
194 double angle = 2 * acos(q1.w);
197 double s = sqrt(1-q1.w*q1.w);
205 return Vector3D(q1.x, q1.y, q1.z);
210 return Vector3D(q1.x / s, q1.y / s, q1.z / s);
221 void scaledAxis(
const Vector3D& vec_in)
223 double theta = vec_in.norm();
228 double s = sin(theta / 2.0);
229 Vector3D W(vec_in / theta * s);
233 w = cos(theta / 2.0);
251 Vector3D rotatedVector(
const Vector3D& v)
const {
252 return (((*
this) * Quaternion(v, 0)) * conjugate()).complex();
262 void euler(
const Vector3D& euler) {
263 double c1 = cos(euler[2] * 0.5);
264 double c2 = cos(euler[1] * 0.5);
265 double c3 = cos(euler[0] * 0.5);
266 double s1 = sin(euler[2] * 0.5);
267 double s2 = sin(euler[1] * 0.5);
268 double s3 = sin(euler[0] * 0.5);
270 x = c1*c2*s3 - s1*s2*c3;
271 y = c1*s2*c3 + s1*c2*s3;
272 z = s1*c2*c3 - c1*s2*s3;
273 w = c1*c2*c3 + s1*s2*s3;
280 Vector3D euler(
void)
const
283 const static double PI_OVER_2 = M_PI * 0.5;
284 double sqw, sqx, sqy, sqz;
292 euler[1] = asin(2.0 * (w*y - x*z));
293 if (PI_OVER_2 - fabs(euler[1]) > EPS_D) {
294 euler[2] = atan2(2.0 * (x*y + w*z),
295 sqx - sqy - sqz + sqw);
296 euler[0] = atan2(2.0 * (w*x + y*z),
297 sqw - sqx - sqy + sqz);
302 euler[2] = atan2(2*y*z - 2*x*w,
309 euler[2] = M_PI - euler[2];
323 void decoupleZ(Quaternion* Qxy, Quaternion* Qz)
const {
325 Vector3D zbt = this->rotatedVector(ztt);
326 Vector3D axis_xy = cross(ztt, zbt);
327 double axis_norm = axis_xy.norm();
329 double axis_theta = acos(clamp(zbt.z, -1.0, 1.0));
330 if (axis_norm > 0.00001)
332 axis_xy = axis_xy * (axis_theta/axis_norm);
335 Qxy->scaledAxis(axis_xy);
336 *Qz = (Qxy->conjugate() * (*this));
343 Quaternion slerp(
const Quaternion& q1,
double t)
345 return slerp(*
this, q1, t);
349 static Quaternion slerp(
const Quaternion& q0,
const Quaternion& q1,
double t) {
351 double omega = acos(clamp(q0.x*q1.x +
354 q0.w*q1.w, -1.0, 1.0));
355 if (fabs(omega) < 1e-10)
359 double som = sin(omega);
360 double st0 = sin((1-t) * omega) / som;
361 double st1 = sin(t * omega) / som;
363 return Quaternion(q0.x*st0 + q1.x*st1,
366 q0.w*st0 + q1.w*st1);
375 Quaternion operator*(
double s,
const Quaternion& q);
Vector4D unit(void) const
Returns unit vector.
Definition: vector4D.h:137
double norm(void) const
Returns Euclidean distance metric extended to 4 dimensions.
Definition: vector4D.h:123
Vector4D()
Constructor.
Definition: vector4D.h:25
void normalize(void)
Divides by Euclidean length.
Definition: vector4D.h:146