#ifndef QUATERNIONS_GLSL
#define QUATERNIONS_GLSL

#define quat vec4

quat quaternionMultiply(quat a, quat b) {
    return vec4(a.w * b.xyz + b.w * a.xyz + cross(a.xyz, b.xyz), a.w * b.w - dot(a.xyz, b.xyz));
}

vec3 quaternionRotate(vec3 pos, vec3 axis, float angle) {
    vec4 q = vec4(sin(angle / 2.0) * axis, cos(angle / 2.0));
    vec4 qInv = vec4(-q.xyz, q.w);
    return quaternionMultiply(quaternionMultiply(q, vec4(pos, 0)), qInv).xyz;
}

vec3 quaternionRotate(vec3 pos, quat q) {
    vec4 qInv = vec4(-q.xyz, q.w);
    vec4 q1 = quaternionMultiply(q, vec4(pos, 0));
    return q1.w * qInv.xyz + qInv.w * q1.xyz + cross(q1.xyz, qInv.xyz);
}

quat quaternionInverse(quat q) {
    return quat(-q.xyz, q.w);
}

quat getRotationToZAxis(vec3 vec) {
	if (vec.z < -0.99999) return quat(1.0, 0.0, 0.0, 0.0);

	return normalize(quat(vec.y, -vec.x, 0.0, 1.0 + vec.z));
}


#endif // QUATERNIONS_GLSL