atan2 mystery

There’s something I really don’t understand. I have a direction between two points (v1.subtract(v2)) and a method to get the bearing from one point to the other in degrees:

public static float toDegrees(Vector3f direction)


if(direction.x == 0)

return (direction.y >= 0) ? 0: 180;

float result = FastMath.atan2(direction.x, direction.y);

return ((result >= 0) ? result: result + FastMath.TWO_PI) * FastMath.RAD_TO_DEG;


Notice that this only works if I pass the x and y in the order other than what the documentation says. I know this atan2 maps directly to Math.atan2, but what is going on?

You might want to define what you expect… ie: what is “working” and “not working”?

Well, the function is called “toDegrees” and is passed a vector probably describing a direction, so… Obviously it’s a direction in the x/y plane.

“Notice that this only works if I pass the x and y in the order other than what the documentation says.”


But not obviously: why are you working in the x,y plane? Usually 3D space is in x,z… and z is backwards for top-down degree rotation.

Also not obviously: can you tell us what degrees you are getting and what you expect to be getting for certain input?

See, the thing is, Math.atan2() works perfectly fine. FastMath.atan2() calls that directly… so there must be a problem in the assumptions you’ve made. But I can’t help until I know what those assumptions are.

Or I can just not bother.

look at the javadoc for Math.atan2. I think it usually take z as first arg (sorry can’t link, writing from the phone). Maybe it is as simple as switching x and {whatever}?

Hmm, I looked at this only for a short time but I think that you have to consider that OpenGL has a coordinate system that works the other way around, so that the angles increase counter-clockwise… am I correct here?

That’s why I asked the OP for more details but the OP was reluctant to help and was happier implying that I’m stupid for not reading his mind.

atan2() takes y, x… ie: rise, run. Since tangent would be sin/cos or y/x this kind of makes sense. It doesn’t matter if it’s C’s atan2() or Math.atan2() or FastMath.atan2().

If you plug reasonable values into these then you will get reasonable results. So the problem is somewhere before atan2() is called. I, too, suspect that it’s some misunderstanding about the OpenGL coordinate system but we can only guess without additional information.

1 Like