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):
Next a single texture with 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);
}
}
}