The coordinate systems
by R. Niehoff
1. The vertex coordinates
There are 3 kinds of coordinates that define the course properties. Let's start with the heightpoints defined in the bitmap "elev.png". Each pixel represents a heightpoint, so we get a net of such points (mesh). The size of the bitmap is given by the number of pixels: nx (width) and ny (height). The x-index goes from 0 ... (nx-1), the y-index from 0...(ny-1).

2. The quad coordinates
The quad coordinates are discret integer values like the vertex coordinates. They are relating to the quads between the heightpoints. You see that a bitmap with width = nx and height = ny consists of (nx-1) * (ny-1) quads. Accordingly the range of indices is from 0...(nx-2) and 0...(ny-2).

3. The real coordinates
The bitmap size is not the real course size, a course can be arbitrarily scaled. The scaling factor has two effects. The greater the factor the lesser detailed will appear the scene - and the better will be the performance. You see, we must make a compromise. Approved values are between 2.0 and 3.0.

Please have in mind that the y-coordinates of the heightmap are now the z-coordinates in the 3D scene. According to the OpenGL rules the z-coordinates are negative because the standard view direction points to -z.
The triangulation of the course
Basically there are two ways of triangulate a mesh: the regular and the alternating triangulation. For two reasons the alternating method is preferred: steep slopes are a bit smoother rendered, and the mesh can be used for a CLOD algorithm like quadtree. Anyway, at the moment a quadtree is not intended but for future enhancements it might be good to have a base which is capable of being extended.

Translating coordinates
The real coordinates at the vertices

Width and height are the scaled course size. The height value yreal can be taken from the elevation array where all heightpoints are stored.
Vertex coordinates (quad coordinates) at real positions

All these formulas are trivial, I needn't explain them. You see that the latter translations reduce the results to integer values - just the requested vertex coordinates. It's recommended to test for extreme positions and move them into valid quads:
if (x > nx-1) x = nx-1; if (y > ny-1) y = ny-1;