Public Group

# Quaternion with Camera

This topic is 1813 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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?

##### Share on other sites

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;

localRotation.x = pAxis.x * halfAngle;
localRotation.y = pAxis.y * halfAngle;
localRotation.z = pAxis.z * halfAngle;

(*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;

localRotation.x = pAxis.x * halfAngle;
localRotation.y = pAxis.y * halfAngle;
localRotation.z = pAxis.z * halfAngle;

(*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

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 28
• 16
• 10
• 10
• 11
• ### Forum Statistics

• Total Topics
634107
• Total Posts
3015549
×