package mikera.vectorz; /** * Static functions for quaternion maths, implemented on Vector4 instances * * Vector4 instance represents (x,y,z,t) tuple, * * Where: quaternion value = x.i + y.j + z.k + t * * @author Mike * */ public class Quaternions { /** * Computes the conjugate of a quaternion * * @param a * @return */ public static Vector4 conjugate(Vector4 a) { return new Vector4(-a.x,-a.y,-a.z,a.t); } /** * Computes the product of two quaternions as a new quaternion * * @param a * @param b * @return */ public static Vector4 mul(Vector4 a, Vector4 b) { double rt=(a.t*b.t)-(a.x*b.x)-(a.y*b.y)-(a.z*b.z); double rx=(a.t*b.x)+(a.x*b.t)+(a.y*b.z)-(a.z*b.y); double ry=(a.t*b.y)-(a.x*b.z)+(a.y*b.t)+(a.z*b.x); double rz=(a.t*b.z)+(a.x*b.y)-(a.y*b.x)+(a.z*b.t); return new Vector4(rx,ry,rz,rt); } /** * Rotates a 3D vector using the given quaternion, returning a new 3D vector * @param q * @param a * @return */ public static Vector3 rotate(Vector4 a, Vector3 b) { double rx=(a.t*b.x)+(a.y*b.z)-(a.z*b.y); double ry=(a.t*b.y)-(a.x*b.z)+(a.z*b.x); double rz=(a.t*b.z)+(a.x*b.y)-(a.y*b.x); return new Vector3(rx,ry,rz); } /** * Create a quaternion that represents a rotation around a given axis vector. * * The axis vector need not be normalised. * * @param axis * @param angle * @return */ public static Vector4 axisAngle(Vector3 axis, double angle) { double ha=angle; // 0.5*angle; double ca=Math.cos(ha); double sa=Math.sin(ha); double x=axis.x, y=axis.y, z=axis.z; double d=(x*x)+(y*y)+(z*z); double ff=sa; if ((d<(0.99999))||(d>1.00001)) { ff/=Math.sqrt(d); } else { ff-=(d-1.0)*0.5; } return new Vector4(ff*x,ff*y,ff*z,ca); } /** * Normalises a quaternion * * @param a * @return */ public static Vector4 normalise(Vector4 a) { double dd=a.elementSquaredSum(); if (dd>0.0) { double d=1.0/Math.sqrt(dd); return new Vector4(a.x*d,a.y*d,a.z*d,a.t*d); } else { return new Vector4(0,0,0,1); } } /** * Inverts a quaternion * * @param a * @return */ public static Vector4 invert(Vector4 a) { double dd=a.elementSquaredSum(); double ff=1.0/dd; return new Vector4(-a.x*ff,-a.y*ff,-a.z*ff,a.t*ff); } }