#include "rts/math/matrix.h" #ifndef RTS_QUATERNION_H #define RTS_QUATERNION_H namespace rts{ template class quaternion { public: T w; T x; T y; T z; void normalize(); void CreateRotation(T theta, T axis_x, T axis_y, T axis_z); void CreateRotation(T theta, vector axis); quaternion operator*(quaternion &rhs); matrix toMatrix3(); matrix toMatrix4(); quaternion(); quaternion(T w, T x, T y, T z); }; template void quaternion::normalize() { double length=sqrt(w*w + x*x + y*y + z*z); w=w/length; x=x/length; y=y/length; z=z/length; } template void quaternion::CreateRotation(T theta, T axis_x, T axis_y, T axis_z) { //assign the given Euler rotation to this quaternion w = (T)cos(theta/2); x = axis_x*(T)sin(theta/2); y = axis_y*(T)sin(theta/2); z = axis_z*(T)sin(theta/2); } template void quaternion::CreateRotation(T theta, vector axis) { CreateRotation(theta, axis[0], axis[1], axis[2]); } template quaternion quaternion::operator *(quaternion ¶m) { float A, B, C, D, E, F, G, H; A = (w + x)*(param.w + param.x); B = (z - y)*(param.y - param.z); C = (w - x)*(param.y + param.z); D = (y + z)*(param.w - param.x); E = (x + z)*(param.x + param.y); F = (x - z)*(param.x - param.y); G = (w + y)*(param.w - param.z); H = (w - y)*(param.w + param.z); quaternion result; result.w = B + (-E - F + G + H) /2; result.x = A - (E + F + G + H)/2; result.y = C + (E - F + G - H)/2; result.z = D + (E - F - G + H)/2; return result; } template matrix quaternion::toMatrix3() { matrix result; T wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; // calculate coefficients x2 = x + x; y2 = y + y; z2 = z + z; xx = x * x2; xy = x * y2; xz = x * z2; yy = y * y2; yz = y * z2; zz = z * z2; wx = w * x2; wy = w * y2; wz = w * z2; result(0, 0) = 1 - (yy + zz); result(0, 1) = xy - wz; result(0, 2) = xz + wy; result(1, 0) = xy + wz; result(1, 1) = 1 - (xx + zz); result(1, 2) = yz - wx; result(2, 0) = xz - wy; result(2, 1) = yz + wx; result(2, 2) = 1 - (xx + yy); return result; } template matrix quaternion::toMatrix4() { matrix result; T wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; // calculate coefficients x2 = x + x; y2 = y + y; z2 = z + z; xx = x * x2; xy = x * y2; xz = x * z2; yy = y * y2; yz = y * z2; zz = z * z2; wx = w * x2; wy = w * y2; wz = w * z2; result(0, 0) = 1 - (yy + zz); result(0, 1) = xy - wz; result(0, 2) = xz + wy; result(1, 0) = xy + wz; result(1, 1) = 1 - (xx + zz); result(1, 2) = yz - wx; result(2, 0) = xz - wy; result(2, 1) = yz + wx; result(2, 2) = 1 - (xx + yy); result(3, 3) = 1; return result; } template quaternion::quaternion() { w=0; x=0; y=0; z=0; } template quaternion::quaternion(T c, T i, T j, T k) { w=c; x=i; y=j; z=k; } } //end rts namespace //#if __GNUC__ > 3 && __GNUC_MINOR__ > 7 //template using rtsQuaternion = rts::quaternion; //#endif #endif