I am looking for some insight into a small problem with unit translations on a grid.
Update and Solved
I solved my own issue. See below for details. Everything in this part of the post turned out to be correct. If anything it can act as a miniature tutorial / example / help for the next person.
Setup
- FBO, VAO, VBO
- 512x448 window
- 64x64 grid
gl_Position = projection * world * position;
projection
is defined byortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);
This is a textbook orthogonal projection function.world
is defined by a fixed camera position at (0, 0)position
is defined by the sprite's position.
Problem
In the screenshot below (1:1 scaling) the grid spacing is 64x64 and I am drawing the unit at (64, 64), however the unit draws roughly ~10px in the wrong position. I've tried uniform window dimensions to prevent any distortion on the pixel size, but now I am a bit lost in the proper way in providing a 1:1 pixel-to-world-unit projection. Anyhow, here are some quick images to aide in the problem.
I decided to super-impose a bunch of the sprites at what the engine believes is 64x offsets.
When this seemed off place, I went about and did the base case of 1 unit. Which seemed to line up as expected. The yellow shows a 1px difference in the movement.
What I Want
Ideally moving in any direction 64-units would output the following (super-imposed units):
Vertices
It would appear that the vertices going into the vertex shader are correct. For example, in reference to the first image the data looks like this in the VBO:
x y x y
----------------------------
tl | 0.0 24.0 64.0 24.0
bl | 0.0 0.0 -> 64.0 0.0
tr | 16.0 0.0 80.0 0.0
br | 16.0 24.0 80.0 24.0
For sake of completeness here is the actual array corresponding to the above movements:
x y z w r g b a s t
-------------------------------------------------------------
tl | 0.0 23.0 0.0 1.0 0.0 0.0 0.0 1.0 0.14210527 0.62650603
bl | 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.14210527 0.76506025
tr | 16.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.2263158 0.76506025
br | 16.0 23.0 0.0 1.0 0.0 0.0 0.0 1.0 0.2263158 0.62650603
-------------------------------------------------------------
-------------------------------------------------------------
tl | 64.0 24.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.21084337
bl | 64.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.3554217
tr | 80.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.08421053 0.3554217
br | 80.0 24.0 0.0 1.0 0.0 0.0 0.0 1.0 0.08421053 0.21084337
// side bar: I know that I have unnecessary data with having a z-axis.
// The engine flips between perspective and orthogonal and I
// haven't selectively started pruning data.
Projection Matrix
The projection matrix for the 512x448 window looks like this:
0.00390625 0.0 0.0 0.0
0.0 0.004464286 0.0 0.0
0.0 0.0 -1.0 0.0
0.0 0.0 0.0 1.0
and is constructed with a textbook orthogonal projection function:
ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);
// explicitly: ortho(-512/2.0f, 512/2.0f, -448/2.0f, 448.0f
ortho(float left, float right, float bottom, float top)
{
projection.setIdentity();
projection.m00 = 2.0f / (right - left);
projection.m11 = 2.0f / (top - bottom);
projection.m22 = -1;
projection.m30 = -(right + left) / (right - left);
projection.m31 = -(top + bottom) / (top - bottom);
projection.m32 = 0;
}
World-view Matrix
The camera's position is just a translation matrix which in this case I just offset by -w/2 and -h/2 to be zero relative to center.
1.0 0.0 0.0 -256.0
0.0 1.0 0.0 -224.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
Solutions I have attempted
player.moveRight()
would move 1-unit with the aspect ratio factored into the equation. So:gridWidth = 64 / 1.14f
. Movement did not fit within the grid.Forced a 512x512 window with a matching orthogonal projection.
Tried various magic numbers and tried to draw correlations between the two.
With that said, all I am left to believe is that I am munging up my actual projection. So, I am looking for any insight into maintaining the 1:1 pixel-to-world-unit projection.