Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with matrices #687

Closed
Crumbler opened this issue Dec 3, 2017 · 5 comments
Closed

Problem with matrices #687

Crumbler opened this issue Dec 3, 2017 · 5 comments

Comments

@Crumbler
Copy link

Crumbler commented Dec 3, 2017

I'm making a simple 3D game using OpenGL 4. I'm loading an .obj file and rotating it horizontally. However, instead of rotating in place, it rotates around the center of the world(starting position of the camera).
Here's how I create the transformation and view matrices:

public static Matrix4 CreateTransformationMatrix(Vector3 translation, Vector3 rotation, float scale) => Matrix4.Identity * Matrix4.CreateTranslation(translation) * Matrix4.CreateRotationX(MathHelper.DegreesToRadians(rotation.X))
                * Matrix4.CreateRotationY(MathHelper.DegreesToRadians(rotation.Y)) * Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(rotation.Z)) * Matrix4.CreateScale(scale);
        public static Matrix4 CreateViewMatrix(Camera camera)
        {
            Matrix4 viewMatrix = Matrix4.Identity * Matrix4.CreateFromAxisAngle(new Vector3(1, 0, 0), camera.pitch) * Matrix4.CreateFromAxisAngle(new Vector3(0, 1, 0), camera.yaw) * Matrix4.CreateTranslation(-camera.position);
            return viewMatrix;
        }

Am I doing it right?
Also I use the built in method for the view matrix:

float aspectRatio = (float)render.Size.Width / (float)render.Size.Height;
            projectMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(FOV), aspectRatio, NEAR_PLANE, FAR_PLANE);

And here is the order in which the matrices are applied in the shader:
projectionMatrix * viewMatrix * transformationMatrix
If you want to take a closer look at the code, I've attached it.
TestOpengl.zip

.

@maxilevi
Copy link

maxilevi commented Dec 4, 2017

Your matrix multiplication order is wrong, scaling goes first, then rotation and at the end translation. I don't think there is an issue with the library.

@Nihlus
Copy link
Contributor

Nihlus commented Dec 4, 2017

Because of how matrices are treated in C# and OpenTK, multiplication order is inverted from what you might expect in C/C++ and GLSL. This is an old artefact in the library, and it's too late to change now, unfortunately.

@Nihlus Nihlus closed this as completed Dec 4, 2017
@daerogami
Copy link
Contributor

@Nihlus This might be a worthwhile MAML remark on the math library methods relating to the aforementioned quirk. Ideally, developers shouldn't have to ask us or dig into the source to figure these things out.

@Silberling
Copy link

Hi all

Because of how matrices are treated in C# and OpenTK, multiplication order is inverted from what you might expect in C/C++ and GLSL. This is an old artefact in the library, and it's too late to change now, unfortunately.

I just created a mini-engine clone from an existing one. I had to change the order everywhere.
I assume this is still an issue?
I am confused. There was a version-major release this year which would have been THE opportunity.
Is there a plan to get this corrected?

@NogginBops
Copy link
Member

NogginBops commented Oct 18, 2020

So this issue is actually more complicated than it seems.

The issue is with column-major or row-major representation of matrices.
OpenGL and GLSL documentation assumes column-major representation, but for legacy reasons opentk uses row-major representation.
OpenGL and GLSL themselves have no bias iirc because all matrix operations are row/column-major agnostic.
OpenTK has a bias because all the matrix creation functions give you back matrices in row-major representation.
A big problem with the math types is that the convention is not clearly stated, and not clearly communicated by the documentation.

The easiest way to get consistent results is to transpose the matrices on upload to glsl, that way the multiplication order is preserved.

There are valid resons to use row-major columns (this is what directx does).
If we look at mathematics, mathematics doesn't care about column-major vs row-major, they are just different conventions, where the order of multiplication gets reversed to get the same meaning.
Though a lot of mathematical literature is written with column-major representation, but some also use row-major.
It is indeed confusing for new users that matrices uploaded with the transpose flag set to false doesn't act the same way in opentk as they do in glsl.
One positive side-effect from the negative one is that people become aware that there are two different representations and will then have to learn something about it.

We are thinking of rethinking the matrix library for opentk 5.0 or 6.0 (whenever there is time to do it), and that one will be a lot more consistent, we hope.
Hopefully we can make OpenTK matrix order agnostic as well, but that might require a significant development effort.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants