One way to look at this is that your viewport is fixed in position, and we rotate the sky so that the central star in your view is directly in front of you. Say you are looking north, then that means rotating the sky first by the negative of the central star’s azimuth to put it directly in front of you. Then rotating the sky down (around the east-west axis) to place the central star on the horizon in front of you.
By applying these two rotations to all of the stars in the sky, we get new positions for them all, and you can simply calculate where they fall on the viewport.
So how? Lets put some coordinates in place. For the 3D space, lets say you are facing “north” which we will say is the positive x direction. They the y-axis points east, and the z-axis points straight up. Your eye is at (0,0,0). For the 2D viewport, we will say that the centre of the viewport is at (0,0), the s-axis points right and the t-axis points up. I could have called these the 3D viewports x and y axes, but with the 3D space have x,y and z axes, the reusing of axis names gets confusing really fast. So just think of the 3D space as (x,y,z) and the 2D space as (s,t).
The viewport itself is placed parallel to the 3D space’s yz plane, so perpendicular to its x axis, and it intersects the x-axis at say (e,0,0), so basically e is the distance of the viewport from your eye.
Projecting a star at (x,y,z) onto the 2D plane is then very simple:
viewport coords = (-ey/x,ez/x).
Since you only can see stars in front of you, (x > 0), only project stars with x > 0. “e” is just a scale factor now; increasing it “zooms in”.
If you are mapping this to a computer screen, you probably need to:
- Scale so the width and height of your viewport match the pixel width and height.
- Add half the pixel width and height to the (s,t) coords. That way the centre of the viewport (0,0) maps to the centre of the screen (width / 2, height / 2).
- Flip the y coordinate (since screen have (0,0) at the top left, not the bottom left). this is just y = height - y;
So this is simple, right ;).
The hard part is figuring out each star’s coordinates and what they map to when you rotate that central star in front of you.
Suppose:
- the central star “c" has
-
- azimuth = azc
- declination = dec
- the star to project “p” onto the 2D viewport has
-
- azimuth = azp
- declination = dep
Then, the (x,y,z) coords of the star “p” on the unit sphere are:
- x = cos(dec)cos(azp - azc)cos(dep) + sin(dec)sin(dep)
- y = sin(azp - azc)cos(dep)
- z = -sin(dec)cos(azp - azc)cos(dep) + cos(dec)sin(dep)
I derived this using 3D matrices. I could show it if you are interested, and I might add it later.
Once you have (x,y,z), then you can use the formula above to project on the 2D viewport.
Also, this got me curious about trying to use 3d transforms in CSS. I set up star web page that demonstrates how it might work. No 3d math!