2
\$\begingroup\$

Preface: In Linux, using C++11, SDL2, GLEW, and OpenGL.

Hello Ladies/Gents,

I am reaching out as I'm stuck on a fairly simple problem that a decade out of school has further hindered. Specifically, I am able to draw a single texture, rotate, grow, extend as I see fit without any real issue. The issue comes when I choose to repeat the texture (at original size or modified size). I am having the hardest time rotating the boxes as well. My debug box rotates without issue, but it is a set of indices.

Could any of you magnificent people offer any pointers or suggestions on how to go about this? I've included the related code bits below.

This is drawRepeat, which handles taking a single texture and it's size (destRect.z = width, destRect.w = height), then repeating through the sizeBounds

void SpriteBatch::drawRepeat(const glm::vec4& destRect, const glm::vec4& uvRect, const glm::vec4& sizeBounds, GLuint texture, float depth, const ColorRGBA8& color, float angle) // angle in radians
{
    // fail without info provided
    if(!m_screenHeight || !m_screenWidth || !m_scale) { GameEngine101::fatalError("No screen width/height or scale specified for drawRepeat!"); }

    int x_iterations = static_cast<int>(sizeBounds.z / destRect.z);
    int y_iterations = static_cast<int>(sizeBounds.w / destRect.w);

    // tmp variables
    glm::vec4 tmpDestRect = glm::vec4(0.0f);

    // create glyphs
    for(uint ix = 0; ix < x_iterations; ix++)
    {
        tmpDestRect = destRect;
        tmpDestRect.x = destRect.x + ( destRect.z * ix ); // something else needs to happen here?

        for(uint iy = 0; iy < y_iterations; iy++)
        {
            tmpDestRect.y = destRect.y + ( destRect.w * iy ); // something else needs to happen here?
            if(angle != 0.0f) { m_glyphs.emplace_back(tmpDestRect, uvRect, texture, depth, color, angle); }
            else { m_glyphs.emplace_back(tmpDestRect, uvRect, texture, depth, color); }
        }
    }
}

This is the constructor for Glyph for rotating textures. Below it is the struct for Vertex and the function for rotatePoint.

Glyph::Glyph(const glm::vec4& destRect,const glm::vec4& uvRect, GLuint Texture, float Depth, const ColorRGBA8& color, float angle) : texture(Texture), depth(Depth)
{
    glm::vec2 halfDimensions(destRect.z / 2.0f, destRect.w / 2.0f);

    // get points centered at origin
    glm::vec2 tl(-halfDimensions[0], halfDimensions[1]); // top left
    glm::vec2 bl(-halfDimensions[0], -halfDimensions[1]); // bottom left
    glm::vec2 tr(halfDimensions[0], halfDimensions[1]); // top right
    glm::vec2 br(halfDimensions[0], -halfDimensions[1]); // bottom right

    // rotate the points
    tl = rotatePoint(tl, angle) + halfDimensions;
    bl = rotatePoint(bl, angle) + halfDimensions;
    tr = rotatePoint(tr, angle) + halfDimensions;
    br = rotatePoint(br, angle) + halfDimensions;

    // top left
    topLeft.setPosition(destRect.x + tl.x, destRect.y + tl.y);
    topLeft.setUV(uvRect.x, uvRect.y + uvRect.w);
    topLeft.color = color;
    // bottom left
    bottomLeft.setPosition(destRect.x + bl.x, destRect.y + bl.y);
    bottomLeft.setUV(uvRect.x, uvRect.y);
    bottomLeft.color = color;
    // top right
    topRight.setPosition(destRect.x + tr.x, destRect.y + tr.y);
    topRight.setUV(uvRect.x + uvRect.z, uvRect.y + uvRect.w);
    topRight.color = color;
    // bottom right
    bottomRight.setPosition(destRect.x + br.x, destRect.y + br.y);
    bottomRight.setUV(uvRect.x + uvRect.z, uvRect.y);
    bottomRight.color = color;
}


struct Vertex
{
    Vertex() {}
    ColorRGBA8 color = COLOR_WHITE; // 4 bytes for R G B A
    glm::vec2 pos = glm::vec2(0.0f);
    glm::vec2 uv = glm::vec2(0.0f); // UV texture coordinates

    void setPosition(float x, float y)
    {
        pos.x = x;
        pos.y = y;
    }

    void setColor(GLubyte R, GLubyte G, GLubyte B, GLubyte A)
    {
        color.r = R;
        color.g = G;
        color.b = B;
        color.a = A;
    }

    void setUV(float u, float v)
    {
        uv[0] = u;
        uv[1] = v;
    }

static glm::vec2 rotatePoint(glm::vec2 pos, float angle)
{
    glm::vec2 newVec;
    newVec.x = pos.x * cos(angle) - pos.y * sin(angle);
    newVec.y = pos.x * sin(angle) + pos.y * cos(angle);
    return newVec;
}

Below is an example of a single texture (white box is my debug box): Single texture, no rotation

Next a single texture with rotation: Single texture, rotation

I have made a comment in the first code block for drawRepeat where I believe the change needs to occur. Next post will contain the repeated textures and rotation. Lack of "reputation" prevents me from posting....


EDIT:

Glyph constructor without rotation:

Glyph::Glyph(const glm::vec4& destRect, const glm::vec4& uvRect, GLuint Texture, float Depth, const ColorRGBA8& color) : texture(Texture), depth(Depth)
{
    // top left
    topLeft.setPosition(destRect.x, destRect.y + destRect.w);
    topLeft.setUV(uvRect.x, uvRect.y + uvRect.w);
    topLeft.color = color;
    // bottom left
    bottomLeft.setPosition(destRect.x, destRect.y);
    bottomLeft.setUV(uvRect.x, uvRect.y);
    bottomLeft.color = color;
    // top right
    topRight.setPosition(destRect.x + destRect.z, destRect.y + destRect.w);
    topRight.setUV(uvRect.x + uvRect.z, uvRect.y + uvRect.w);
    topRight.color = color;
    // bottom right
    bottomRight.setPosition(destRect.x + destRect.z, destRect.y);
    bottomRight.setUV(uvRect.x + uvRect.z, uvRect.y);
    bottomRight.color = color;
}

More-recent drawRepeat:

void SpriteBatch::drawRepeat(const glm::vec4& destRect, const glm::vec4& uvRect, const glm::vec4& sizeBounds, GLuint texture, float depth, const ColorRGBA8& color, float angle) // angle in radians
{
    // fail without info provided
    if(!m_screenHeight || !m_screenWidth || !m_scale) { GameEngine101::fatalError("No screen width/height or scale specified for drawRepeat!"); }

    int x_iterations = static_cast<int>(sizeBounds.z / destRect.z);
    int y_iterations = static_cast<int>(sizeBounds.w / destRect.w);

    // tmp variable
    glm::vec4 tmpDestRect = destRect;

    // rotate by angle, converted from radians to degrees, on the z-axis
    glm::mat4 groupRotation;
    groupRotation = glm::rotate(groupRotation, glm::degrees(angle), glm::vec3(0.0f, 0.0f, 1.0f));

    GLint pUniformM = m_glsl->getUniformLocation("model");
    glUniformMatrix4fv(pUniformM, 1, GL_FALSE, &groupRotation[0][0]);

    // create glyphs
    for(uint ix = 0; ix < x_iterations; ix++)
    {
        tmpDestRect.x = destRect.x + ( destRect.z * ix ); // set X position

        for(uint iy = 0; iy < y_iterations; iy++)
        {
            tmpDestRect.y = destRect.y + ( destRect.w * iy ); // set Y position

            // rotate on angle, if exists
            //if(angle != 0.0f) { m_glyphs.emplace_back(tmpDestRect, uvRect, texture, depth, color, angle); }
            //else { m_glyphs.emplace_back(tmpDestRect, uvRect, texture, depth, color); }
            m_glyphs.emplace_back(tmpDestRect, uvRect, texture, depth, color);
        }
    }
}
\$\endgroup\$
1
\$\begingroup\$

You need to rotate the images as a unit instead of separately. This means, you need to apply the rotation after local transformation. Like this:

vPosition = singleImageRotation * cornerPosition; // Probably unnecessary step
vPosition = singleImagePosition + vPosition;
vPosition = groupRotation * vPosition;
vPosition = groupPosition + vPosition;

In this example the singleImageRotation and groupRotation are matrices that rotates your vertices. Also singleImagePosition is the image position in relation to the group's pivot point.

\$\endgroup\$
  • \$\begingroup\$ Relatively new to OpenGL still (sadly), please excuse the somewhat "obvious" questions: is 'vPosition' indicating the vertex position? If so, would this mean that I should be applying the local transformations and rotations per vertex, to all those involved in the "group"? \$\endgroup\$ – Beau B. Jan 9 '17 at 18:09
  • \$\begingroup\$ That is correct. \$\endgroup\$ – Lasse Jan 9 '17 at 18:10
  • \$\begingroup\$ Glorious. Will continue my hunt and I greatly appreciate your time and insight! :) \$\endgroup\$ – Beau B. Jan 9 '17 at 18:11
  • \$\begingroup\$ Lasse, if it's not too much trouble, could I pester you further to elaborate on how one might go about working out the singleImageRotation and groupRotation? \$\endgroup\$ – Beau B. Jan 10 '17 at 0:10
  • \$\begingroup\$ @BeauB. Sure thing. You are welcome to join the chat to ask questions from the community as I am not always available. I can answer your questions when I have the time to do so. Meanwhile you could read this and this tutorial for more information about transformations in OpenGL. \$\endgroup\$ – Lasse Jan 10 '17 at 11:24

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.