Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a projectile that is moving around the world (in a ballistics trajectory right now). I am currently keeping track of its position and velocity. I want to draw it oriented to its velocity, so that it is facing the direction it is going. This seemed like as good of a time as any to try to understand quaternions so I was attempting to solve the orientation problem using them.

Here is my drawing code:

var alignmentVector = Vector3.Normalize(velocity);
var rotationAxis = Vector3.Cross(Vector3.Up, alignmentVector);
var rotationAngle = (float)Math.Acos(Vector3.Dot(Vector3.Up, alignmentVector));
var rotationQuat = Quaternion.CreateFromAxisAngle(rotationAxis, rotationAngle);

var transform = Matrix.CreateScale(5.0f) *
                Matrix.CreateFromQuaternion(rotationQuat) *
                Matrix.CreateTranslation(position);


PresentationHelper.Draw(model, transform); //This just draws the model using the transform parameter as the world matrix

This kinda of works, but not really. In fact, I am having a hard time finding the words to describe what is happening with it. It looks like its tracking for a little while then it goes off course and becomes flattened(is that possible????)

Am I on the right track with the quaternions and can my code be fixed? If not what is a good approach to solving it?

share|improve this question
    
Quaternions and matrices can basically do the same thing with a few minor pros and cons for each. For your case, the matrix would serve you better because you are keying your orientation off one of the Matrix's basis vectors (velocity -> matrix's forward) and there really isn't an easy to apply correlation there with the quaternion. –  Steve H Dec 7 '11 at 13:52
    
Is this the same question as gamedev.stackexchange.com/questions/15070/… –  Tetrad Dec 7 '11 at 16:50
add comment

2 Answers 2

up vote 0 down vote accepted

If you were to take the cross idea a step further, you could finish your desired orientation as a matrix and pass it that way (and which could be converted to a quaternion if needed).

Vector3 forward = Vector3.Normalize(velocity);
Vector3 Right = Vector3.Normalize(Vector3.Cross(forward, Vector3.Up));
Vector3 modelUp = Vector3.Cross(right, forward);

float scale = 5.0f;
Matrix orientation = Matrix.Identity;
orientation.Forward = forward * scale;
orientation.Right = right * scale;
orientation.Up = modelUp * scale;
orientation.Translation = position;

presentationHelper.Draw(model, orientation);

OR... If you want Xna to do all that crossing & normalizing behind the scenes, you could do this:

Matrix orientation = Matrix.CreateWorld(position, Vector3.Normalize(velocity), Vector3.Up);
Matrix transform = Matrix.CreateScale(5.0f) * orientation;
presentationHelper.Draw(model, transform);
share|improve this answer
    
edited to add scale. –  Steve H Dec 7 '11 at 13:56
add comment

Quaternions always represent a rotational transform. When you use a quaternion to specify a model's orientation, that quaternion specifies a rotation away from identity. And in XNA, a model with an identity rotation will point toward Vector3.Forward.

With that in mind, I believe your problem is here:

var rotationAngle = (float)Math.Acos(Vector3.Dot(Vector3.Up, alignmentVector));

You're comparing your alignmentVector, which is your desired forward vector, with Vector3.Up. Instead, you should be comparing against Vector3.Forward.

Further reading: Orienting a model to face a target

share|improve this answer
    
That looks to work, however the "up" part of the projectile changes over the course of the path. Is there a way to make it point to world up? –  Mr Bell Dec 7 '11 at 13:48
    
If you want to point your projectile toward Vector3.Up (or down), you still need to transform the Vector3.Forward vector; however, you should save the projectile's quaternion, and use it next frame to derive an up vector, rather than using Vector3.Up in your calculations: Vector3.Transform(Vector3.Up, quaternionLastFrame). This ensures your projectile won't suddenly flip. –  Blair Holloway Dec 7 '11 at 22:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.