public class Quaternion{ public float w, x, y, z; // constructor public Quaternion(){ } // constructor public Quaternion(float qw, float qx, float qy, float qz){ w=qw;x=qx;y=qy;z=qz; } // FromAxisAngle - creates a quaternion to do a rotation, // from an axis and an angle in degrees public static Quaternion fromAxisAngle(float angle, float ax, float ay, float az){ float sinangle, cosangle; float length; // we need to normalize the axis values so that they are a unit vector length = (float) Math.sqrt(ax*ax+ay*ay+az*az); ax /= length; ay /= length; az /= length; // precalculate the sin and cos of the angle so we dont need to keep using the sin function // NOTE: sin uses radians, and we want degrees as angles, so the formula is // angle = angle * (PI / 180); // sinangle = sin(angle/2); // which is the same as saying // sinangle = sin(angle * PI/360); sinangle = (float) Math.sin(angle * Math.PI / 360.0); cosangle = (float) Math.cos(angle * Math.PI / 360.0); return new Quaternion(cosangle, ax * sinangle, ay * sinangle, az * sinangle); } // GetConjugate - returns the conjugate of the current quaternion public Quaternion getConjugate(){ return new Quaternion(w, -x, -y, -z); } // Multiply - Multiplies two quaternions togeather Quaternion multiply(Quaternion q2){ Quaternion Result = new Quaternion(); float w1, x1, y1, z1; float w2, x2, y2, z2; w1 = w; x1 = x; y1 = y; z1 = z; w2 = q2.w; x2 = q2.x; y2 = q2.y; z2 = q2.z; Result.w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2; Result.x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2; Result.y = w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2; Result.z = w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2; return Result; } // RotatePoint - Rotates the given point by the current quaternion Quaternion rotatePoint(float px, float py, float pz){ Quaternion p = new Quaternion(0,px,py,pz); Quaternion cq = this.getConjugate(); Quaternion result; // now for the magic (q * P * q') result = (this.multiply(p)).multiply(cq); return result; } Quaternion slerp(Quaternion q2, float time){ float dotprod; float angle; double sinangle; float a, b; Quaternion result; float w1, x1, y1, z1; float w2, x2, y2, z2; w1 = w; x1 = x; y1 = y; z1 = z; w2 = q2.w; x2 = q2.x; y2 = q2.y; z2 = q2.z; // get the dot product, and ensure it's >= 0 // to ensure the shortest path (< 180) is chosen dotprod = w1*w2 + x1*x2 + y1*y2 + z1*z2; if(dotprod < 0.0f){ w1 = -w1; x1 = -x1; y1 = -y1; z1 = -z1; dotprod = w1*w2 + x1*x2 + y1*y2 + z1*z2; } // get the angle angle = (float) Math.acos(dotprod); if(angle == 0){ return new Quaternion(w1,x1,y1,z1); } sinangle = Math.sqrt(1 - (dotprod * dotprod)); // calculate the multipliers a = (float)(Math.sin(angle * (1.0f - time)) / sinangle); b = (float)(Math.sin(angle * time) / sinangle); // create the result quaternion return new Quaternion(a*w1+b*w2, a*x1+b*x2, a*y1+b*y2, a*z1+b*z2); } }