0
\$\begingroup\$

When I draw a quad that is rotating the aspect ratio of the quad gets messed up and the size changes.

Gif of what is happening

I am confident it has something to do with the way I calculate the size because that is relative to the width and height of the screen, I just don't know why the aspect ratio would change since the aspect ratio of the screen doesn't change.

Code of transformationMatrix creation:

        Matrix4f matrix = Maths.createTransformationMatrix(
                new Vector2f(
                        gui.getPosition().getX() / Display.getWidth() * 2 - 1 + gui.getSize().getX() / Display.getWidth(),
                        -gui.getPosition().getY() / Display.getHeight() * 2 + 1 - gui.getSize().getY() / Display.getHeight()
                ), gui.getRotation()
                ,new Vector2f(
                        gui.getSize().getX() / Display.getWidth(),
                        gui.getSize().getY() / Display.getHeight()
                )
        );
        shader.loadTransformation(matrix);

The x size, y size, x position and y position are in pixels, if you put in 1600 pixels for x position and the screen is 1600 pixels wide it will fill the whole screen. The calculation that is done here will translate those sizes to a value that the shaders will display on the screen.

I had tried calculating the sizes in a different way:

gui.getSize().getX() / (float) (Display.getWidth() * Math.abs(Math.cos((Math.toRadians(gui.getRotation())))) + Display.getHeight() * Math.abs(Math.sin((Math.toRadians(gui.getRotation()))))),

but this does not work at all, my thought process was that if it is sideways it should use Display.getHeight to calculate the x size and if it is vertical it should use Display.getWidth. This does work for 0, 90, 180 and 270 degrees rotation, but in between it gets smaller and weird. Of course I've also done this for the x position but then cos and sin switched around.

video of this method

And this is the createTransformationMatrix method:

public static Matrix4f createTransformationMatrix(Vector2f translation, float rotation, Vector2f scale) {
    Matrix4f matrix = new Matrix4f();
    matrix.setIdentity();
    Matrix4f.translate(translation, matrix, matrix);
    Matrix4f.rotate((float) Math.toRadians(rotation), new Vector3f(0, 0, 1), matrix, matrix);
    Matrix4f.scale(new Vector3f(scale.x, scale.y, 1f), matrix, matrix);
    return matrix;
}
\$\endgroup\$
  • \$\begingroup\$ I'm not fluent in OpenGL, but it looks like you're using a convenience method to build a matrix with a translation, rotation, and scale. These types of methods usually apply scale first, then rotation, then translation. That means the scale gets applied to your quad BEFORE it's rotated. The scale you're trying to apply looks like a screenspace calculation, which should happen after your rotation transform. So, it looks to me like you want to remove the screenspace component from this method, and concatenate it in a second step before passing it to the shader. I may be misreading it though. \$\endgroup\$ – DMGregory Jan 18 '16 at 23:41
  • \$\begingroup\$ @DMGregory I have included the createTransformationMatrix method, do you still think it is first scaled and then rotated? \$\endgroup\$ – The Coding Wombat Jan 18 '16 at 23:52
  • \$\begingroup\$ Sorry, I'm not sure. I've used similar methods in other environments, but I'm not fluent enough in OpenGL to give you a definite answer. It does look like your code assumes the x-axis of the quad aligns with the x-axis of the screen though, which will not be generally true for rotated quads, so I think the gui.getSize and Display.GetWidth should probably not appear together in one argument like that. \$\endgroup\$ – DMGregory Jan 18 '16 at 23:56
0
\$\begingroup\$

Try this instead:

Matrix4f modelMatrix = new Matrix4f();
        modelMatrix.m00 =  2.0f / (float) Display.getWidth();
        modelMatrix.m11 = -2.0f / (float) Display.getHeight();
        modelMatrix.m30 = -1;
        modelMatrix.m31 =  1;

I have no idea what gui.getSize().getX() / Display.getWidth() was suppose to do, so I left it out from above. But if you intend to scale or translate some object after converting it to pixels, I recommend creating a second matrix with those transformation and multiplying them together to create a third matrix rather then modifying this one.

What I created above it an orthographic projection matrix which translates from pixel values e.i. [0,width] to [-1,1] and [0,height] to [1,-1]. This also means the origin is in the top-left corner. So if you now assume pixel coordinates and multiply any transformation with the projection matrix at the end, no distortions should occur.

Remember that the order you multiply matrices matter.

Example:

Matrix4f modelMatrix = new Matrix4f();
        modelMatrix.m00 =  2.0f / (float) Display.getWidth();
        modelMatrix.m11 = -2.0f / (float) Display.getHeight();
        modelMatrix.m30 = -1;
        modelMatrix.m31 =  1;

// No special trickery or dividing by width, just use pixel coordinates.
// The projection matrix takes care of converting the pixel coordinates.
Matrix4f modelMatrix = Maths.createTransformationMatrix(
    new Vector2f(
        gui.getPosition().getX(),
        gui.getPosition().getY())
    , gui.getRotation()
    , new Vector2f(
        1.0f,
        1.0f
    )
);

Matrix4f modelProjMatrix = Matrix4f.mul(projectionMatrix, modelMatrix, null);
shader.loadTransformation(modelProjMatrix);

The projectionMatrix can be shared by all of your geometry. Again I don't really understand what the gui.getSize().getX() is suppose to be doing in your code but I included it.

\$\endgroup\$
  • \$\begingroup\$ gui.getSize().getX() was getting the width of the quad I was trying to render. This is the code I used for creating the quad: GuiTexture phone = new GuiTexture(loader.loadTexture("phone"), new Vector2f(1600 / 2 - 300 / 2, 50), 0, new Vector2f(300, 300 * 2.05f)); \$\endgroup\$ – The Coding Wombat Jan 19 '16 at 14:47
  • \$\begingroup\$ @TheCodingWombat I don't know what parameters GuiTexture takes so nothing helpful there, but did you get it to work? Do you have any questions regarding my answer? \$\endgroup\$ – Christer Jan 19 '16 at 14:56
  • \$\begingroup\$ It are the position (x and y) and size(x and y) of the quad I render in pixels, I have not fully read your answer yet, I'm not at my home computer \$\endgroup\$ – The Coding Wombat Jan 19 '16 at 16:34
  • \$\begingroup\$ This does not seem to render anything when i create new quads with small sizes and positions and also not when I create them with large sizes and positions, also, this transformationmatrix will be the same for all rendered quads, that means you can't rotate individual rendered things right? \$\endgroup\$ – The Coding Wombat Jan 19 '16 at 17:11
  • \$\begingroup\$ @TheCodingWombat Remember that coordinates are now in pixel coordinates. And yes this transformation matrix will be the same for all rendered quads, but no you can individually rotate quads. Just use a different model matrix. Example added, look through my answer again. \$\endgroup\$ – Christer Jan 19 '16 at 18:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.