Coordinates vs pixels
Since I’m interested in using raylib to visualize some computations, I want to almost exclusively work with real world \(x\) and \(y\) coordinates (in meters), and then only at the end (when drawing to the screen) convert those to screen coordinates (in pixels) since that’s what raylib expects.
I also want the \(y\)-direction to point up instead of down (world origin at bottom left).
If we use subscripts “w” to mean world, and “s” to mean screen, and \(p\) and \(q\) for the \(x\)- and \(y\)-axis conversion factors between screen (pixels) and world (meters), we have:
\[x_{\text{s}} = px_{\text{w}}\]
\[y_{\text{s}} = -qy_{\text{w}} + h\]
where \(h\) is
screen_height in pixels.
And so, likewise, to go back the other way:
\[x_{\text{w}} = \frac{x_{\text{s}}}{p}\]
\[y_{\text{w}} = \frac{1}{q} (h-y_{\text{s}})\]
To find those constants \(p\), \(q\), and \(h\), suppose, for example, I want:
- the window to be 800 pixels wide
- \(x\) to go from 0 \(\rightarrow\) 10 m
- \(y\) to go from 0 \(\rightarrow\) 8 m
When \(x_{\text{w}}\) = 10 m, that means \(x_{\text{s}}\) must be 800 px. Thus \(p\) = 80 px/m.
As for \(q\), since we know that the
width/height ratios of the world and the screen are the same, it follows
that the max \(y_{\text{s}}\) is 640
px, and thus \(h\), is 640 px. If we
then put in the pair \(y_{\text{s}}\) =
0 px and \(y_{\text{w}}\) = 8 m, we get
\(q\) = 640 px / 8 m = 80 px/m. The
same as \(p\)! Of course, this is no
surprise, because we are keeping our aspect ratio on the screen the same
as in the real world. :)
Without the units present, the equations above now look like:
\[x_{\text{s}} = 80 x_{\text{w}}\]
\[y_{\text{s}} = -80 y_{\text{w}} + 640\]
and
\[x_{\text{w}} = \frac{x_{\text{s}}}{80}\]
\[y_{\text{w}} = \frac{1}{80} (640-y_{\text{s}})\]
Here’s the code (“wo” means “world”, “sc” means “screen”):
see ~/temp/foo.pyRun it and see how the screen is “10 m wide” and “8 m tall”.