Make a 3d arrow show direction to a point

Started by
3 comments, last by JCWeinberg 15 years, 3 months ago
I am workin on a 3d game,within this game I need a 3D HUD arrow that points to the location of the next checkpoint. I have something that almost works, but really freaks out if I'm not near the same Y plane. Anyone see anything obviously wrong? Or know of a different way to get what I'm trying to get? Thanks, - Josh The following code is XNA: public static Matrix ArrowMatrix(Vector3 ArrowPosition, Vector3 TargetPosition, Vector3 backwards) { Vector3 dif = TargetPosition - ArrowPosition; Vector3 back = backwards; back.Normalize(); dif.Normalize(); float theta = (float)System.Math.Acos(Vector3.Dot(dif, back)); Vector3 cross = Vector3.Cross(back, dif); cross.Normalize(); Quaternion targetQ = Quaternion.CreateFromAxisAngle(cross, theta); Matrix WorldMatrix = Matrix.CreateFromQuaternion(targetQ);// *Matrix.CreateTranslation(ArrowPosition); return WorldMatrix; }
Advertisement
I think it should theoretically work, except for the cases where your back and dif vector make a flat (180 deg) corner, in which case your cross product would result in a [0,0,0] vector.

But besides that, it does seem really prone to floating point inaccuracy, for example this line:

float theta = (float)System.Math.Acos(Vector3.Dot(dif, back));

would probably give INF or NaN when the result of your dot product exceeds the -1 - 1 range (which it mathematically shouldn't but can still happen due to rounding problems).

But anyway, I think a better way would be to just get three perpendicular, normalized vectors, where one of them is the dif vector, and use those as the rows of your matrix):

Vector3 dif = TargetPosition - ArrowPosition;
forward.Normalize();
Vector3 tangent1 = Vector3.CrossProduct(dif,up);
tangent1.Normalize();
Vector3 tangent2 = Vector3.CrossProduct(tangent1,dif);
tangent2.Normalize();

Matrix3 mat;
mat.SetRow(0,tangent1);
mat.SetRow(1,tangent2);
mat.SetRow(2,dif);

this assumes that the arrow without any rotation points down the z axis.

(disclaimer: untested:))
That Acos worries me ... that's going to give you one of two values and only be right half the time.

I don't think you have to do a rotation. You know the three primary axes thta you want your arrow to project onto, they are:

Forward: s (the direction vector from the arrow to the target)
Right: s×y (I think y is upwards in D3D?)
Up: s×(s×y)

So your transformation matrix is just the combination of those three vectors. Or the inverse of same – at this time of night I can't work out which one is right <.< ...

It doesn't work if the target is directly above or below the arrow, because it can't choose a suitable right-vector. I think you need to special case this situation and work out a good one, probably the player's current right-vector.

Edit: sniped, heh. Glad to see we chose the same answer.
Thanks for the help guys, that got me on the right track. But I can't seem to get that into the space of the character. The arrow is supposed to indicate how the player is supposed to move to get to that point, the arrow itself isn't "in" world space.

So what I tried was taking your suggestion and then multiplying it by the characters orientation matrix, but that didn't quite work.

...any help down that road?

- Josh
I finally got this working. I took the Matrix that was constructed using the instructions above and multiplied it by the camera View Matrix rotation. Works perfectly now.

Thanks again for the help!

- Josh

This topic is closed to new replies.

Advertisement