Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Quaternion with Camera


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
1 reply to this topic

#1 EarthBanana   Members   -  Reputation: 989

Like
0Likes
Like

Posted 02 February 2014 - 01:12 AM

I have switched everything over to using quaternions.. The only problem I'm having now is with the camera - if you just rotate a quaternion about the x axis so that you are pointed towards the sky, and then about y axis (assuming z is in to the screen) to look to the right (and using delta mouse pos to determine rotation amount) you end up with a rolled camera. I get why and I understand that is how the math works (I programmed the math after all) - the quaternion, after the first rotation about the x axis, has a new local y axis that is different than the world's y axis

 

My question is this.. Is there any way to rotate the camera about the world's y axis and not it's local y axis while using only one quaternion to store rotation information within the camera?



Sponsor:

#2 EarthBanana   Members   -  Reputation: 989

Like
0Likes
Like

Posted 02 February 2014 - 03:28 AM

Nevermind - I have figured it out.. basically just remembering that order of multiplication makes a big difference

 

Rotation as I described before:

void NSQuaternion::rotate(const NSVec3Df & pAxis, float pAngle)
{
	NSQuaternion localRotation;

	float halfAngle = sinf(DegreesToRadians((pAngle/2.0f)));
	localRotation.x = pAxis.x * halfAngle;
	localRotation.y = pAxis.y * halfAngle;
	localRotation.z = pAxis.z * halfAngle;
	localRotation.w = cosf(DegreesToRadians(pAngle / 2.0f));

	(*this) = localRotation * (*this);
	normalize();
}

And with the camera working the way that I actually want it to..

void NSQuaternion::rotate(const NSVec3Df & pAxis, float pAngle)
{
	NSQuaternion localRotation;

	float halfAngle = sinf(DegreesToRadians((pAngle/2.0f)));
	localRotation.x = pAxis.x * halfAngle;
	localRotation.y = pAxis.y * halfAngle;
	localRotation.z = pAxis.z * halfAngle;
	localRotation.w = cosf(DegreesToRadians(pAngle / 2.0f));

	(*this) = (*this) *localRotation;
	normalize();
}

The operator* function for my Quaternion is the following

NSQuaternion NSQuaternion::operator*(const NSQuaternion & pRHSQuat) const
{
	NSQuaternion ret;
	ret.x = w*pRHSQuat.x + x*pRHSQuat.w + y*pRHSQuat.z - z*pRHSQuat.y;
	ret.y = w*pRHSQuat.y - x*pRHSQuat.z + y*pRHSQuat.w + z*pRHSQuat.x;
	ret.z = w*pRHSQuat.z + x*pRHSQuat.y - y*pRHSQuat.x + z*pRHSQuat.w;
	ret.w = w*pRHSQuat.w - x*pRHSQuat.x - y*pRHSQuat.y - z*pRHSQuat.z;
	return ret;
}

I will use the second version of the function as the final version because I can get the Up, Target, or Right vector any time with these:

NSVec3Df NSQuaternion::getTargetVec() const
{
	return NSVec3Df(2.0f*x*z - 2.0f*w*y, 2.0f*y*z + 2.0f*w*x, 1.0f - 2.0f*x*x - 2.0f*y*y);
}

NSVec3Df NSQuaternion::getUpVec() const
{
	return NSVec3Df(2.0f*x*y + 2.0f*w*z, 1.0f - 2.0f*x*x - 2.0f*z*z, 2.0f*y*z - 2.0f*w*x);
}

NSVec3Df NSQuaternion::getRightVec() const
{
	return NSVec3Df(1.0f - 2.0f*y*y - 2.0f*z*z, 2.0f*x*y - 2.0f*w*z, 2.0f*x*z + 2.0f*w*y);
}

And finally.. to get the rotation transform for the quat

NSMatrix4Df NSQuaternion::getRotationMatrix() const
{
	NSMatrix4Df retMat;
	retMat.setRow(NSVec4Df(getRightVec(), 0.0f), 0);
	retMat.setRow(NSVec4Df(getUpVec(), 0.0f), 1);
	retMat.setRow(NSVec4Df(getTargetVec(), 0.0f), 2);
	return retMat;
}

And just for anyone who cares.. a working interpolation function that I use for animation

NSQuaternion NSQuaternion::getInterpolatedQuaternion(const NSQuaternion & pFirst, 
		const NSQuaternion & pSecond, 
		float pScalingFator)
{
	NSQuaternion ret;
	NSQuaternion second = pSecond;

	float cosHalfTheta = getCosHalfAngle(pFirst,pSecond);


	if (cosHalfTheta < 0) 
	{
	  second = second * -1.0f;
	  cosHalfTheta = -cosHalfTheta;
	}

	// make sure we dont go out of acos domain
	if ( abs(cosHalfTheta ) >= 1.0)
		return pFirst;

	// Calculate more expensive values.
	float halfTheta = acos(cosHalfTheta);
	float sinHalfTheta = sinf(halfTheta);

	// if sin of theta = 0 (or something close) then just
	// take  point exactly between the two quats
	if (fabs(sinHalfTheta) < 0.000001)
		return pFirst*0.5f + second*0.5f;

	float ratioA = sin((1 - pScalingFator) * halfTheta) / sinHalfTheta;
	float ratioB = sin(pScalingFator * halfTheta) / sinHalfTheta;
	ret = pFirst*ratioA + second*ratioB;
	ret.normalize();
	return ret;
}

float NSQuaternion::getCosHalfAngle(const NSQuaternion & pFirst, const NSQuaternion & pSecond)
{
	return pFirst.x*pSecond.x + pFirst.y*pSecond.y + pFirst.z*pSecond.z + pFirst.w*pSecond.w;
}

Edited by EarthBanana, 02 February 2014 - 03:31 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS