How to get angles from coordinates using an arctangent lookup table
There are quite a few routines that convert 3D Cartesian coordinates into angles, but they all end up calling the GetHypotenuseAngle routine, which in turn calls the GetAngleFromCoords routine to convert a 3D Cartesian vector into pitch and yaw angles.
The calculation is essentially the reverse of the conversion from angles to coordinates (see the deep dive on converting angles to coordinates for details). It takes two Cartesian coordinates and returns the angle from the right-angled triangle that the coordinates form when they are the adjacent and opposite sides (so that's the angle of the hypotenuse).
A classic use is to find the yaw angle of a point when given that point's x-coordinate and z-coordinate - for example, the yaw angle of a tile coordinate. Because the routine is general-purpose and can be applied to any pair of orthogonal axes, the variables are expressed in terms of deltas; the other classic use is finding the angles of vectors between objects, which is where the delta terminology comes from.
The specific calculation in the GetAngleFromCoords routine is this:
angle(Hi Lo) = arctan( z-delta / x-delta )
To see what this represents, consider the first example, where we are trying to find the yaw angle of a tile coordinate from the perspective of the player. The calculation is shown in the following triangle, which is an overhead view of the player, with the player in the bottom-left corner. The player is looking straight ahead, which means they are looking upwards in the following diagram, and there's a tile in front of and to the right of the player:
tile
+
.´|
.´ |
.´ | z-delta
^ .´ |
| .´ |
| .´ a |
player +------------+
x-delta
If the tile is x-delta to the right of the player and z-delta ahead of the player (so x-delta and z-delta are the coordinates of the tile relative to the player), then we can calculate the yaw angle a of the tile relative to the player by using the definition of tangent and arctangent:
opposite z-delta
tan(a) = -------- = -------
adjacent x-delta
so:
( z-delta )
a = arctan( ------- )
( x-delta )
To get the arctan, we use the two lookup tables at arctanHi and arctanLo. These tables between them contain a range of 16-bit values as follows:
FOR I%, 0, 256 EQUB INT(0.5 + 32 * ATN(I% / 256) * 256 / ATN(1)) NEXT
So the Y-th entry in the table contains 32 * arctan(Y / 256), multiplied by a scale factor of 256 / ATN(1) and rounded up to the nearest integer. The scale factor ensures that values in the table range from 0 to 32 * 255, with the maximum value when the angle is 45 degrees (i.e. when the adjacent and opposite sides are equal, so opposite / adjacent = tan(I%) = 1). This ensures that the table contains maximum accuracy for the angle range 0 to 45 degrees, which is a good enough range as objects with yaw angles greater than 45 degrees are off-screen.
So the lookup table lets us convert a tile coordinate into the tile's yaw angle, without having to do any maths; all we need is a simple lookup, which is quick and easy.
To see this calculation in action, take a look at the following routines: GetObjectAngles, GetObjVisibility, GetObjPointAngles, GetPitchAngleDelta and GetTileViewAngles.