///////////////////////////////////////////////////////////////////////////////////////////////
// QUATERNION OPERATORS
///////////////////////////////////////////////////////////////////////////////////////////////
CQuaternion CQuaternion::operator/(float factor)
{
return CQuaternion(x / factor, y / factor, z / factor, w / factor);
}
void CQuaternion::operator/=(float factor)
{
x /= factor;
y /= factor;
z /= factor;
w /= factor;
}
bool CQuaternion::operator==(CQuaternion q)
{
if (q.x == x && q.y == y && q.z == z && q.w == w) return true;
return false;
}
bool CQuaternion::operator!=(CQuaternion q)
{
if (q.x == x && q.y == y && q.z == z && q.w == w) return false;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// MULTIPLIES QUATERNIONS (NON-COMMUTATIVE)
///////////////////////////////////////////////////////////////////////////////////////////////
CQuaternion mult(CQuaternion q1, CQuaternion q2)
{
CQuaternion r;
/*r.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
r.y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
r.z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
r.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;*/
r.x = q1.x * q2.w + q1.w * q2.x + q1.y * q2.z - q1.z * q2.y;
r.y = q1.y * q2.w + q1.w * q2.y + q1.z * q2.x - q1.x * q2.z;
r.z = q1.z * q2.w + q1.w * q2.z + q1.x * q2.y - q1.y * q2.x;
r.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
return r;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// RETURNS THE NORM OF A QUATERNION
///////////////////////////////////////////////////////////////////////////////////////////////
float norm(CQuaternion q)
{
return sqrtf((q.x * q.x) + (q.y * q.y) + (q.z * q.z) + (q.w * q.w));
}
///////////////////////////////////////////////////////////////////////////////////////////////
// NORMALIZES A QUATERNION
///////////////////////////////////////////////////////////////////////////////////////////////
void normalize(CQuaternion &q)
{
q /= norm(q);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// COMPUTES THE CONJUGATE OF A QUATERNION
///////////////////////////////////////////////////////////////////////////////////////////////
CQuaternion conjugate(CQuaternion q)
{
return CQuaternion(-q.x, -q.y, -q.z, q.w);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// CONVERSION FROM QUATERNION TO VECTOR3
///////////////////////////////////////////////////////////////////////////////////////////////
CVector3 quat_to_vector3(CQuaternion q)
{
return CVector3(q.x, q.y, q.z);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// CONVERSION FROM VECTOR3 TO QUATERNION
///////////////////////////////////////////////////////////////////////////////////////////////
CQuaternion vector3_to_quat(CVector3 v)
{
return CQuaternion(v.x, v.y, v.z, 0.0f);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// ROTATES THE CAMERA AROUND THE PROVIDED AXIS
///////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::rotate(float angle, float x, float y, float z)
{
CQuaternion rotate, view;
rotate.x = x * sin(angle / 2.0f);
rotate.y = y * sin(angle / 2.0f);
rotate.z = z * sin(angle / 2.0f);
rotate.w = cos(angle / 2.0f);
// this->view is the camera's view vector, as mentioned in the problem description
view = vector3_to_quat(this->view);
view = mult(mult(rotate, view), conjugate(rotate));
this->view = quat_to_vector3(view);
}