1
\$\begingroup\$

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?

\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$
    – Steve H
    Dec 7, 2011 at 13:52
  • \$\begingroup\$ Is this the same question as gamedev.stackexchange.com/questions/15070/… \$\endgroup\$
    – Tetrad
    Dec 7, 2011 at 16:50

2 Answers 2

0
\$\begingroup\$

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);
\$\endgroup\$
1
  • \$\begingroup\$ edited to add scale. \$\endgroup\$
    – Steve H
    Dec 7, 2011 at 13:56
2
\$\begingroup\$

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

\$\endgroup\$
2
  • \$\begingroup\$ 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? \$\endgroup\$
    – Mr Bell
    Dec 7, 2011 at 13:48
  • \$\begingroup\$ 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. \$\endgroup\$ Dec 7, 2011 at 22:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .