Matrix Handedness Confusion

Started by
4 comments, last by Nanoha 7 years, 8 months ago

Say i'm making a math library, i've decided to use a row major, so i know what components of the matrix hold what data.

Next up i want to implement some rotation. Following this khan academy video i have to essentially transpose the matrix he comes up with to compensate for my matrix being row-major.

Now, looking at an article like this one, i initially assumed that the rotation of a left-handed matrix would be the transpose of a right handed matrix, and that i would have to decide if my matrix class was using a left handed or right handed coordinate system at this point. However, after implementing the rotation i no longer think this is the case. It would seem like the transpose comes about because of the basis vectors being stored in rows v columns.

So, my question, when exactly does handedness of a matrix really matter? Is handedness just a question of how the projection matrix is constructed? IE, i know OpenGL is historically right-handed, but if i make my own projection matrix that is left-handed and load it into OpenGL will that application now be left-handed?

Does handedness only matter once there is a viewer?

Or am i missing something here?

Advertisement

This is a very confusing topic (element ordering, handedness, etc) and I am also very confused with it so bare that in mind with how valid this reply is. Firstly handedness, matrix memory layout and matrix mathematical layout are separate things which doesn't help matters.

Handedness matters in that if you want one axis to be positive right and another axis to be positive up (conventional) then the final axis either increases as it goes away in front of you (left handed) or it decreases as it goes away in front of you from you (right handed). There's then rotations to consider, do they also follow left/right handed rules (left: positive rotates clockwise, right: positive rotates anti-clockwise). You then have to take all that into account when you move things and when you setup your camera etc. With shaders I'm not entirely sure if much of that even matters now because the space is defined by you, by how you setup your transforms and projections etc. I think OpenGL being considered right-handed is based on fixed-function when you used to have all the functions for creating projections and view matricies etc. From what I've read, OpenGL actually ends up being left handed in device space anyway. It's all far too much for my head.

As far as how you lay things out in memory goes, it doesn't matter too much since mostly you will be abstracting all the maths away behind functions and operations. It doesn't affect the maths one bit (or it shouldn't). Your choice certainly has implications, row-major is convenient for accessing rows for example but then transferring that to a shader might require a transpose.

Then there's the mathematical implications of your choice and this depends on whether you consider a vector to be a horizontal or a vertical matrix. Assuming a 4x4 matrix, if you think of a vector as a vertical matrix (1 wide by 4 high for example) then when you multiply you will have to do matrix*vector but if you think of it as horizontal (e.g. 4 wide, 1 high) then you have to do vector*matrix. I don't know about HLSL but in GLSL it will decide based on the order you choose but then you may need a transpose. For example these two are the same:


// mvp was originally a column-major memory matrix
gl_Position = mvp*vec4(position, 0.0, 1.0);" // vec4 treated as a column
gl_Position = vec4(position, 0.0, 1.0)*transpose(mvp); // vec4 treated as a row
When you do your own matrix code and build, for example, a translation matrix (using a function) then you will have to decide if you will be post multiplying vectors or pre multiplying them because that will affect how you build the translation (and other transforms). You could do like GLSL does and decide based on usage but I think that just makes your code open to confusion. For example:

Matrix translation;
translation.LoadTranslation(1, 2, 3);
Vector position(0, 0, 0);
Vector a = position*translation;
Vector b = translation*position;

Both of those can be coded to work just like in GLSL but only one will work as intended and that depends on how you built the translation matrix. You would have to transpose one to make it work as intended.

There are pros and cons to all choices but as long as you are consistent I don't think it matters too much. I wish there was some full blown article that covered all these things because I'm still not 100% sure of any of it either. Hopefully someone here has more of a clue than I do.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

That's actually a great roundup of exactly what is constantly confusing me! I'm hoping continous exposure will make me have a more solid understanding of the topic ;)

In trying to figure the problem out, i ran accross this stackexchange question, the answer to it provided some insight

The answer says if we agree on a certain order of matrices (i, j, k) to be right handed, then (j, i, k) is left handed.

Now, the opportune word there is agree. That's not saying one is right handed v the other is left handed, this is all dependent on the viewer.

Unrelated, there is one more idea i've read about visualizing + and - z.

Visualizing a right handed coordinate system is like keeping X and Y axis flat, and adding a Z axis that points up.

Now, if you want your right handed system to have Y be up, you have to rotate the coordinate system, this makes Z be negative.

Visualizing a left handed coordinate system, the X / Y plane aligns with the screen, and the Z axis is just added to it to point positive into the screen.

But, like yourself i'm also constantly confused on this, and my understanding is constantly changing!

Say i'm making a math library, i've decided to use a row major, so i know what components of the matrix hold what data.

If you're using "horizontal matrices", as above, then row major array indexing will keep the data more readable (an array of four basis vectors). But if you're using "vertical matrices" then column major array indexing will keep the data more readable (the exact same array of four basis vectors as the other situation!!).

Visualizing a left handed coordinate system, the X / Y plane aligns with the screen, and the Z axis is just added to it to point positive into the screen.

I label my thumb, index and middle fingers as X, Y and Z, and make them perpendicular like a "finger guns" gesture. On each hand, X is up, Y is aiming at you, but Z direction is swapped :)
But spin your hands around and you get other arrangements. If you fix X as across a screen to the right and Z as into the screen, then right handed has Y as down, while left handed has Y as up. That's basically the conventions of whether the bottom left or top left should be the origin of a drawing canvas :)
So there's not a single right handed coordinate system and a single left handed coordinate system - handedness is a property that you can tell about a coordinate system once you know which ways its axes point.
The only place this matters in D3D/GL is the final NDC/clip-space coordinate system, which determines if Y is up or down (or if Z is in or out...). If you're using different conventions, the only matrix that requires any changes is your projection matrix, which transforms from your coordinate system into clip space/NDC.

As for your matrix library:
Most coordinate systems define a positive rotation to be clockwise when looking down the axis of rotation away from the origin. You can implement that definition without knowing anything else about the coordinate system, such as its handedness :)

Does handedness only matter once there is a viewer?

Yes - this is right. Your maths (and physics etc) code is (should be!) exactly the same irrespective of whether the viewing system is right or left handed.

I also like to use the 'finger guns' to understand handedness. I'm fairly sure that's why they are called left/right handed because they come from the respective hand. For rotations there is also the left/right handed rules which is used with things like electro magnetism and screws but it also works great for maths. You imagine your thumb is the axis of rotation (positive in the direction your thumb is pointing) and just give someone a 'thumbs up'. The direction your fingers coil is the direction of positive rotation. Right handed your fingers then go counter clockwise when looking down the axis and left handed they go clockwise when looking down the axis. There is far less confusion here and the standard seems to be the right handed version (based on how sin and cos work I think).

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

This topic is closed to new replies.

Advertisement