PDA

View Full Version : How do I make a quartenion from a forward vector?



NeXEkho
05-26-2010, 02:49 AM
I've looked around and the general consensus is "make a lookat matrix, convert to quaternion". But this just doesn't seem to work. I get a rotation but it's not one that correlates properly to the direction vector. I'm no maths whizz and I barely understand quaternions (though other parts of the program that manipulate quaternions are working great) and so I can't determine the problem.



//Normalize velocity vector.

float fVecX = tsMyPhysics->fVelX, fVecY = tsMyPhysics->fVelY, fVecZ = tsMyPhysics->fVelZ;

float fScalar = sqrt( ( fVecX * fVecX ) + ( fVecY * fVecY ) + ( fVecZ * fVecZ ) );

fVecX /= fScalar;
fVecY /= fScalar;
fVecZ /= fScalar;

GLfloat glfLookAtMe[ 3 ][ 3 ] = { { fVecX, fVecY, fVecZ }, { 0.0f, 1.0f, 0.0f }, { fVecX, fVecY, fVecZ } };

//Convert to 3x3 matrix.

tsMyObject->fAW = sqrt( 1.0f + glfLookAtMe[ 0 ][ 0 ] + glfLookAtMe[ 1 ][ 1 ] + glfLookAtMe[ 2 ][ 2 ] / 2.0f );

//Convert to quartenion.

float fDivisor = 4.0f * tsMyObject->fAW;

tsMyObject->fAX = ( glfLookAtMe[ 1 ][ 2 ]- glfLookAtMe[ 2 ][ 1 ] ) / fDivisor;
tsMyObject->fAY = ( glfLookAtMe[ 2 ][ 0 ]- glfLookAtMe[ 0 ][ 2 ] ) / fDivisor;
tsMyObject->fAZ = ( glfLookAtMe[ 0 ][ 1 ]- glfLookAtMe[ 1 ][ 0 ] ) / fDivisor;

Thinking it might be a problem to do with left vs. right handed matrices, I've tried swapping the column and row numbers but it had no effect. It's not perpendicular to what I am after or inverted on X or anything; it's just pointing in a seemingly random direction.

todayman
05-30-2010, 10:39 AM
I'm kind of confused as to what you actually want to accomplish.

This is what I know:
You have a velocity, and it's represented by a vector.

I'm not sure how you want to convert this to a quaternion. Is the quaternion supposed to rotate the view to point along this vector?

NeXEkho
05-31-2010, 02:59 AM
I have a velocity which I normalize and then I want to turn this forward vector into a quaternion for use in my rendering pipeline. The idea is that the projectile will point in the direction of movement rather than north, as missiles rarely do such a thing.

todayman
05-31-2010, 11:28 AM
The math isn't that bad, so long as you don't try to visualize 4-dimensional quaternion space...

A quaternion stores an axis of rotation and an angle. The quaternion for a rotation should be normalized. Generally, the real component of the quaternion is related to the angle, while the imaginary parts store the axis (and the angle...). The real component is cosine of the angle, while the imaginary part is the unit vector along the axis multiplied by the sine of the angle.

Assuming the forward vector and the original direction are unit vectors, the cosine of the angle is the dot product of them. Also, original cross forward is perpendicular to the two vectors (i.e. along the axis of rotation) and has magnitude of the sine of the angle. The resulting quaternion, then, has the dot product in the real part and the cross product in the imaginary parts.

If this doesn't work, then try swapping the order in which you cross the vectors.

lobbel
06-16-2010, 05:57 AM
Here are is some piece of code converting a quaternion to a rotation matrix and vector/angle to quaternion. Actually the vector in the second code part is the rotation axis.


template<class T>
void Quaternion<T>::getRotationMatrix(Matrix4<T>&amp; matrix)
{
T len = this->length();

T s = (len > (T)0) ? ((T)2 / len) : (T)0;
T xs = x * s, ys = y * s, zs = z * s;
T wx = w * xs, wy = w * ys, wz = w * zs;
T xx = x * xs, xy = x * ys, xz = x * zs;
T yy = y * ys, yz = y * zs, zz = z * zs;

matrix.get(0,0) = (T)1 - (yy + zz); //11
matrix.get(0,1) = xy - wz; //12
matrix.get(0,2) = xz + wy; //13
matrix.get(0,3) = (T)0; //14

matrix.get(1,0) = xy + wz; //21
matrix.get(1,1) = (T)1 - (xx + zz); //22
matrix.get(1,2) = yz - wx; //23
matrix.get(1,3) = (T)0; //24

matrix.get(2,0) = xz - wy; //31
matrix.get(2,1) = yz + wx; //32
matrix.get(2,2) = (T)1 - (xx + yy); //33
matrix.get(2,3) = (T)0; //34

matrix.get(3,0) = (T)0; //41
matrix.get(3,1) = (T)0; //42
matrix.get(3,2) = (T)0; //43
matrix.get(3,3) = (T)1; //44

}




template<class T>
void Quaternion<T>::setRotation(Vector3<T>&amp; axis, T&amp; angle)
{
T len = length(axis);

if(len > (T)0.00001)
{
T scale = sin((T)(0.5) * angle) / len;

x = axis.x * scale;
y = axis.y * scale;
z = axis.z * scale;
w = cos((T)(0.5) * angle);
}
else
{
x = (T)0;
y = (T)0;
z = (T)0;
w = (T)1;
}
}


regards,
lobbel