I'm working on a 3D flight game and I'd like to implement a simple "navigation arrow" pointing at the next waypoint in world which the player has to fly to.

I have position of both airplane (=camera) and the target and also orientation of the airplane (in form of quaternion). But sadly I can't figure out correct way to use them to get the arrow pointing at the target regardless the airplane yaw/pitch/roll.

The arrow was already working once, but only when the airplane was in horizontal orientation. But when the airplane was tilted, the tilt was not reflected in the arrow transform.

Here's my code (it might not be accurate, as I'm desperately trying anything that could help) to get the arrow rotation

Vector3 target = ...;

Vector3 dir = new Vector3(0, 0, -1); // initial airplane direction
dir.rotateBy(airplaneQuat); // current airplane direction

double angle = Math.acos(target.dot(dir));
Vector3 axis = target.cross(dir);

I think my problem is the fact that the airplane can fly upside down and in other riddiculous orientations, and I just cannot visualize all the transforms in my head. I'll be happy for any help.

UPDATE: Based on Cong's answer I came up with working solution. Here's the pseudocode. It could be improved, but the arrow behaves sufficiently accurate by now, just the way I indended.

Vector3 dir = target.position;

Quaternion q = airplane.orientation;
q = q.conjugate();

Vector3 up = Vector3(0, 1, 0);
Matrix4 mat = Matrix4.createLookAt(dir, up);

Matrix4 transform = Matrix4(); // identity
transform.translate(0, -0.85, 0); // move to the bottom of the screen
transform.scale(0.2); // just scaling the model
  • \$\begingroup\$ Is it a 3D arrow, or a 2D one? Is it pointing along compass directions, or is it pointing relative to the current camera view? \$\endgroup\$ – Trevor Powell Mar 5 '13 at 23:11

What you are looking for is the LookAt algorithm. OpenGL already has that in a nice function: gluLookAt, although it multiplies the current matrix instead of returning it to you so you may need some push/pop trickery to get at it.

If you want to do it yourself, there are two ways; by constructing a transformation matrix, or by using quaternions. Here's the abridged version of this tutorial:

void LookAt(Matrix4& orient, const vec3& target, const vec3& Up)
    vec3 ZAxis = target - orient.WAxis();
    vec3 XAxis = CrossProduct(Up, ZAxis);
    vec3 YAxis = CrossProduct(ZAxis, XAxis);

Where orient is your arrow's transform matrix (position and rotation), target is where you want it to point at, and Up is a suitable "up" direction.

Here's another link which may be useful: https://stackoverflow.com/questions/349050/calculating-a-lookat-matrix


The "gluLookAt" function (as mentioned by Cong Xu, is definitely useful, but I find this to be even better:


It is really the same thing as a lookAt matrix, but gives you a deeper understanding of its functionality.

Using tangent space vectors, you can easily rotate an object into a given position. It is actually really important to understand how this works (I think) if you want a firm understanding of 3D vector math, but you can just as well use it without digging too deep.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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