• Create Account

## 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.

### #1EarthBanana  GDNet+

1765
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?

### #2EarthBanana  GDNet+

1765
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;

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, 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.