# Can't figure out projection transform

I'm trying to fugure out all the spaces transformations, and currently have some inconsistency I can't understand. I'm working on a 2D game (so we assuming Z is always 0 for now), on a device with 960x544 resolution. So, as far as I understand my World Space is left-top (0, 0) to right-bottom (959, 543), with Y axis inverted (going down). Let w = 960, h = 544. To transform it to Eye Space we need to move (0, 0) to center of the screen, so it would be simple translation, viewT:

1, 0, 0, -w/2
0, 1, 0, -h/2
0, 0, 1, 0
0, 0, 0, 1


Next step is Clip Space. I want all world space to be rendered so it's just scaling. But we also need to invert Y axis and that's the part I'm unsure of. My assumption would be that we just add minus sign for the Y scale, and thus projT:

2/w, 0, 0, 0
0, -2/h, 0, 0
0, 0, 1, 0
0, 0, 0, 1


Then viewProjT = projT * viewT would give me:

2/w, 0, 0, -1
0, -2/h, 0, 1
0, 0, 1, 0
0, 0, 0, 1


But in samples I have, "reference" matrix is:

2/w, 0, 0, 0
0, -2/h, 0, 0
0, 0, 1, 0
-1, 1, 0, 1


i.e. it's my viewProjT, but transposed. And that's the part I don't understand. Can someone clarify why I need to transpose matrix to get correct matrix? Is this somehow related to inverting Y axis?

Note: I'm using this, as a basis for my calculations. And image to illustrate my World and Clip spaces:

## 1 Answer

Found answer myself. Long story short, it all depends on assumptions on both how matrices are applied to points (row vector or column vector) and how matrices are stored in memory (row major or column major). These differ for DirectX and OpenGL, there DX usually uses row vector and row major matrices, and OpenGL the other types. But in both cases, due to double "error" compensation, given mathematical matrix (i.e. we not assuming any memory layout here, just indices):

m11 m12 m13 m14
m21 m22 m23 m24
m31 m32 m33 m34
m41 m42 m43 m44


translations will always be in array indices 12, 13 and 14. So for DirectX (row major) this will map to m41, m42, m43 and for OpenGL (column major) to m14, m24, m34. For more details on subject see here.

AFAIU in my calculations I used column vector assumption (and indeed, if I apply my transformation matrix to column vector I get correct results). But in fact my system uses (relatively of course, which system to use is a user's choice, but I just want to stick with existing samples) row vectors, so I need to either change assumption in calculations or just transpose final matrix.