# Extracting directional vectors from quaternions

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

## Recommended Posts

After spending some time with my newly learned knowledge of quaternions and integrating them into my engine, I've started to put together a first-person simulation. All rotations and animations look good, except for what I try to clamp my direction. My SetDirection() and other functions that set the orientation don't seem to be working correctly. There's a couple ways I tried to do this but none have worked... Here's what I have so far: Using the vector direction and creating a rotation matrix
void Update()
{
// ...
if ( fabs(m_camera.GetDirection().Y) > 0.8f )
{
Vector3 dir = m_camera.GetDirection();
if ( dir.Y > 0 )
dir.Y = 0.8f;
else
dir.Y = -0.8f;
dir.Normalize();
Vector3 right = dir ^ Vector3(0.0f, 1.0f, 0.0f);
Vector3 up = right ^ dir;
m_camera.SetOrientation(Quaternion(right,up,dir)); // calls Quaternion::SetFromAxes()
}
// ...
}

Vector3 Camera::GetDirection() const
{
return GetOrientation().Rotate(Vector3(0.0f, 0.0f, -1.0f));
}
Vector3 Quaternion::Rotate(const Vector3 & vec) const
{
Quaternion v(0.0f,vec);
return Quaternion(*this * v * this->operator~()).vec;
}
void Quaternion::SetFromAxes(
const Vector3 & xAxis,
const Vector3 & yAxis,
const Vector3 & zAxis)
{
Matrix3 mat;

mat[0] = xAxis.X;
mat[1] = xAxis.Y;
mat[2] = xAxis.Z;

mat[3] = yAxis.X;
mat[4] = yAxis.Y;
mat[5] = yAxis.Z;

mat[6] = zAxis.X;
mat[7] = zAxis.Y;
mat[8] = zAxis.Z;

SetFromRotationMatrix(mat);
}
void Quaternion::SetFromRotationMatrix( const Matrix3 & m ) // from Ogre3D
{
float trace = m[0] + m[4] + m[8];
float root;

// 'w' is the real part and 'vec' is a Vector3 of the imaginary components
if ( trace > 0.0f )
{
root = sqrtf(trace + 1.0f);
w = 0.5f * root;
root = 0.5f / root;
vec.X = (m[7] - m[5]) * root;
vec.Y = (m[2] - m[6]) * root;
vec.Z = (m[3] - m[1]) * root;
}
else
{
static long s_iNext[3] = { 1,2,0 };
long i = 0;
if ( m[4] > m[0] )
i = 1;
if ( m[8] > m[i*3+i] )
i = 2;
long j = s_iNext;
long k = s_iNext[j];

root = sqrtf(m[i*3+i] - m[j*3+j] - m[k*3+k] + 1.0f);
float * quat[3] = {&vec.X, &vec.Y, &vec.Z};

*quat = 0.5f * root;
root = 0.5f / root;
w = (m[k*3+j] - m[j*3+k]) * root;
*quat[j] = (m[j*3+i] + m[i*3+j]) * root;
*quat[k] = (m[k*3+i] + m[i*3+k]) * root;
}
}


Use cached out angle values
if ( fabs(m_camera.GetPitch()) > 3.14f/3.0f )
{
if ( m_camera.GetOrientation().GetPitch() > 0 )
m_camera.SetPitch(3.14f/3.0f);
else
m_camera.SetPitch(-3.14f/3.0f);

}
void Camera::Pitch( float angle )
{
Quaternion q;
Vector3 axis;
axis = GetOrientation().Rotate(Vector3(1.0f, 0.0f, 0.0f));
q.SetFromAxis( angle, axis );
q.Normalize();
IncOrientation(q);
SetOrientation(GetOrientation().Normalized());
}
void Camera::SetPitch( float angle )
{
float a = m_orientation.GetPitch();
Pitch( angle - a );
}
float sWQuaternion::GetPitch() const
{
Vector3 yAxis = GetYAxis();
return atan2(yAxis.X, yAxis.Y);
}
sWVector3D sWQuaternion::GetYAxis() const
{
// 'w' is real part, 'vec' is a Vector3 of imaginary part in this quat
float fTx  = 2.0f*vec.X;
float fTy  = 2.0f*vec.Y;
float fTz  = 2.0f*vec.Z;
float fTwx = fTx*w;
float fTwz = fTz*w;
float fTxx = fTx*vec.X;
float fTxy = fTy*vec.X;
float fTyz = fTz*vec.Y;
float fTzz = fTz*vec.Z;

return Vector3(fTxy-fTwz, 1.0f-(fTxx+fTzz), fTyz+fTwx);
}


Is there anything noticeably wrong with my code? Using either method?

1. 1
Rutin
24
2. 2
3. 3
JoeJ
18
4. 4
5. 5

• 38
• 23
• 13
• 13
• 17
• ### Forum Statistics

• Total Topics
631706
• Total Posts
3001835
×