Sign in to follow this  
Mercenarey

Rotating a quaternion around an axis...

Recommended Posts

I thought I had this right, but some testing has given unwanted results. Here is what I have:
// camera forwards the calls to its quaternion
m_camera->RotateYaw(DegreeToRadian(45.0f));
m_camera->RotatePitch(DegreeToRadian(15.0f));

//------------------------------------------------
//------------------------------------------------
void Quaternion::RotateYaw(float a_theta)
{
	Vector3 l_axis_y;
	GetAxisY(l_axis_y);			// gets this quaternions Y-axis

	RotateAroundAxis(a_theta, &l_axis_y);
}

//------------------------------------------------
//------------------------------------------------
void Quaternion::RotatePitch(float a_theta)
{
	Vector3 l_axis_x;
	GetAxisX(l_axis_x);			// gets this quaternions X-axis

	RotateAroundAxis(a_theta, &l_axis_x);
}

//------------------------------------------------
//------------------------------------------------
void Quaternion::RotateAroundAxis(float a_theta, const Vector3* a_axis)
{
	Quaternion l_quat;

	l_quat.x = a_axis->x * sin(a_theta * 0.5f);
	l_quat.y = a_axis->y * sin(a_theta * 0.5f);
	l_quat.z = a_axis->z * sin(a_theta * 0.5f);
	l_quat.w = cos(a_theta * 0.5f);

	(*this) *= l_quat;
}


This code I would have expected to work like normal euler angle rotation, and the result should have been a camera pitched slightly, without any tilt. But there is a tilt (http://www.mercenaries.ws/tiltedquat.jpg), which I don't understand. When I rotateYaw() alone, I have no problem. I always have a problem with pitch, however, no matter if I do pitch alone or not, or in what order I call it. What am I doing wrong? Edit: Oh, btw, I will provide the GetX(), GetY() and GetZ() methods as well, just in case it will become interesting.
//------------------------------------------------
//------------------------------------------------
void Quaternion::GetAxisX(Vector3& a_axis_x) const
{
	//Real fTx  = 2.0*x;
	float fTy  = 2.0f*y;
	float fTz  = 2.0f*z;
	float fTwy = fTy*w;
	float fTwz = fTz*w;
	float fTxy = fTy*x;
	float fTxz = fTz*x;
	float fTyy = fTy*y;
	float fTzz = fTz*z;

	a_axis_x.Set(1.0f-(fTyy+fTzz), fTxy+fTwz, fTxz-fTwy);
}

//------------------------------------------------
//------------------------------------------------
void Quaternion::GetAxisY(Vector3& a_axis_y) const
{
    float fTx  = 2.0f*x;
    float fTy  = 2.0f*y;
    float fTz  = 2.0f*z;
    float fTwx = fTx*w;
    float fTwz = fTz*w;
    float fTxx = fTx*x;
    float fTxy = fTy*x;
    float fTyz = fTz*y;
    float fTzz = fTz*z;

    a_axis_y.Set(fTxy-fTwz, 1.0f-(fTxx+fTzz), fTyz+fTwx);
}

//------------------------------------------------
//------------------------------------------------
void Quaternion::GetAxisZ(Vector3& a_axis_z) const
{
	float fTx  = 2.0f*x;
	float fTy  = 2.0f*y;
	float fTz  = 2.0f*z;
	float fTwx = fTx*w;
	float fTwy = fTy*w;
	float fTxx = fTx*x;
	float fTxz = fTz*x;
	float fTyy = fTy*y;
	float fTyz = fTz*y;

	a_axis_z.Set(fTxz+fTwy, fTyz-fTwx, 1.0f-(fTxx+fTyy));
}


Share this post


Link to post
Share on other sites
Isn't this line incorrect:

(*this) *= l_quat;


When you rotate a quaternion P by a quaternion l_quat, the result should be:

l_quat * P * l_quat_conj

Where l_quat_conj is the quaternion conjugate of l_quat:

http://mathworld.wolfram.com/QuaternionConjugate.html


(Or perhaps I've overlooked something?)

Share this post


Link to post
Share on other sites
Your answer got me thinking, and I looked into the line you mentioned, and I remmebered that quaternion multiplication is not commutative. Do'h!

I tried to invert the multiplication order, and it seemed to fix the problem.

Now it reads like this:
(*this) = l_quat * *this;


Thanx alot.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this