OpenGL - translation stretches and distorts sprite

1k views Asked by At

I am loosely following the very handy tutorial at opengl-tutorial.org. I've been able to create a mesh, draw a sprite to it, and rotate and scale that mesh perfectly fine.

However, I'm running into some issues when trying to translate the mesh. (pictures below)

Here's an update function on the sprite:

    Transform* transform = static_cast<Transform*>(owner->GetComponent(CID_TRANSFORM));

    glUseProgram(shaderID_);

    glm::mat4 projection = glm::perspective(45.0f , 4.0f / 3.0f, 0.1f, 100.0f);

    glm::mat4 view = glm::lookAt(
        glm::vec3(3, 3, 3),
        glm::vec3(0, 0, 0),
        glm::vec3(0, 1, 0)
        );

    glm::mat4 model = transform->GetModelMatrix();

    glm::mat4 mvp = projection * view * model;

    GLuint matrixID = glGetUniformLocation(shaderID_, "MVP");

    glUniformMatrix4fv(matrixID, 1, GL_FALSE, &mvp[0][0]);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_);
    glUniform1i(samplerID_, 0);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer_);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer_);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glDrawArrays(GL_TRIANGLES, 0, 3 * 2);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

And here's the getModelMatrix function:

glm::mat4 Transform::GetModelMatrix()
{
    glm::mat4 trans = glm::mat4(
        1.0f, 0.0f, 0.0f, translation.x,
        0.0f, 1.0f, 0.0f, translation.y,
        0.0f, 0.0f, 1.0f, translation.z,
        0.0f, 0.0f, 0.0f, 1.0f);

    float xCos = glm::cos(rotation.x);
    float xSin = glm::sin(rotation.x);
    float yCos = glm::cos(rotation.y);
    float ySin = glm::sin(rotation.y);
    float zCos = glm::cos(rotation.z);
    float zSin = glm::sin(rotation.z);

    glm::mat4 xRotation = glm::mat4(
        1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, xCos, -xSin, 0.0f,
        0.0f, xSin, xCos, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    glm::mat4 yRotation = glm::mat4(
        yCos, 0.0f, ySin, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f,
        -ySin, 0.0f, yCos, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    glm::mat4 zRotation = glm::mat4(
        zCos, -zSin, 0.0f, 0.0f,
        zSin, zCos, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    glm::mat4 rot = xRotation * yRotation * zRotation;

    glm::mat4 sca = glm::mat4(
        scale.x, 0.0f, 0.0f, 0.0f,
        0.0f, scale.y, 0.0f, 0.0f,
        0.0f, 0.0f, scale.z, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    return trans * rot * sca;
}

Here is the sprite at the origin viewed from (3, 3, 3). first image

Here is the sprite translated to (1, 0, 0) viewed from (3, 3, 3). second image

1

There are 1 answers

4
Reto Koradi On BEST ANSWER

Matching OpenGL, GLM stores matrices in column major order. The constructors also expect elements to be specified in the same order.

However, your translation matrix is specified in row major order:

glm::mat4 trans = glm::mat4(
    1.0f, 0.0f, 0.0f, translation.x,
    0.0f, 1.0f, 0.0f, translation.y,
    0.0f, 0.0f, 1.0f, translation.z,
    0.0f, 0.0f, 0.0f, 1.0f);

To specify the matrix in the correct column major order, this needs to be:

glm::mat4 trans = glm::mat4(
    1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    translation.x, translation.y, translation.z, 1.0f);