# 2D HUD overlay drawing based on 3D coordinates and camera azimuth and elevation

Assume you have the 3d coordinates of the player and another unit N as well as the azimuth and elevation of a camera always looking at the player. In the following illustration the sun would be the camera of course:

(source: permetix.com)

Let's say one wants to draw something on a different transparent window (not using the game window or any hooks) that is always displayed on top of the unit. An example would be TurboHUD for Diablo. In the linked video you can see that it displays affixes using textboxes right on top of the blue elite mobs.

In Diablo doing this is much simpler since the camera cannot be rotated and moved thus only simple projections depending on the distance are necessary, but what about situations with more degrees of freedom? How can one estimate 2d coordinates to draw at that match the position of the 3d units on the screen without access to more than described in the first paragraph? What is the mathematical background and what are the necessary computations?

So I came up with a solution that is basically a World-to-Camera matrix chained with a Camera-to-Projection matrix. For this I only need to rotate the vector (cameraDistance, 0, 0) based on elevation and azimuth to start with and apply the following computations:

cameraDirection = normalize(cameraPosition - playerPosition)
cameraRight = normalize(crossProduct((0, 0, 1), cameraDirection))
cameraUp = normalize(crossProduct(cameraPosition, cameraRight))


This is essentially the Gram-Schmidt proccess and yields the following view matrix

With R_i being the components of the cameraRight, U_i the components of the cameraUp, D_i the components of the cameraDirection and P_i the components of the cameraPosition vector respectively. Thus an object with homogenized coordinates v would appear at V * v for the camera. To project this to the screen I am using the following projection matrix:

The value r is the aspect ratio, FOV the field of view in degrees, F the distance of the far plane and N the distance of the near plane.

To get the final 2d coordinates the vector u = P * V * v must be dehomogenized and thus all components must be divided by the fourth component of u. Finally the first and second component are values in [-1,1] thus one must add 1 and multiply with 0.5 then with the width or height respectively to map the relative positions to screen coordinates.