Skip to content

Instantly share code, notes, and snippets.

@gszauer
Created June 6, 2013 00:26
Show Gist options
  • Save gszauer/5718413 to your computer and use it in GitHub Desktop.
Save gszauer/5718413 to your computer and use it in GitHub Desktop.
The simplest method of projecting a 3D point onto a 3D screen assumes that we are in the camera coordinate system; that is all points are specified in relation to the viewer, who is assumed to be at (0, 0, 0). Assuming that the coordinates of the center of the display are at (0, 0), +X is right and +y is up:
screen_x = vector.x / vector.z;
screen_y = vector.y / vector.z;
In the vga (0, 0) is top left and +Y is going down; Lets account for the skewed center and inverted y:
screen_x = vector.x / vector.z + HALF_SCREEN_WIDTH;
screen_y = -1.0 * vector.y / vector.z + HALF_SCREEN_HEIGHT;
While correct, the above code will greatly exaggerate the effects of of perspective. To somewhat offset this a fixed multiplier should be applied:
screen_x = vector.x * perspective_compensate / vector.z + HALF_SCREEN_WIDTH
screen_y = -1.0 * vector.y * perspective_compensate / vector.z + HALF_SCREEN_HEIGHT
The key to understanding the perspective_compensate is understanding field of view.
tan(hfov / 2) = HALF_SCREEN_WIDTH / distance_to_monitor
tan(vfov / 2) = HALF_SCREEN_HEIGHT / distance_to_monitor
horizontal_perspective_compensate = HALF_SCREEN_WIDTH / tan(horizontal_fov / 2)
vertical_perspective_compensate = HALF_SCREEN_HEIGHT / tan(vertical_fov / 2)
Lets plug in some numbers
horizontal_perspective_compensate = (320 / 2) / tan(60 / 2)
160 / tan(30)
~277
60 degrees is ideal for both horizontal and vertical field of view
This is a pretty good solution, however we are still left with the problem of using a correct aspect ratio
aspect_ration = vertical_resolution / horizontal_resolution
With aspect correction the final projected coordinates are
screen_x = vector.x * horizontal_perspective_correct / vector.z + HALF_SCREEN_WIDTH
screen_y = -1.0 * vector.y * vertical_perspective_correct / vector.z + HALF_SCREEN_HEIGHT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment