Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: ability to use rotated images with setTextureRect  (Read 13520 times)

0 Members and 1 Guest are viewing this topic.

superjoe

  • Newbie
  • *
  • Posts: 7
    • View Profile
ability to use rotated images with setTextureRect
« on: August 06, 2014, 04:43:49 pm »
Some texture packers rotate images 90 degrees clockwise or counter-clockwise for efficient packing. When loading textures, the OpenGL code would look something like this:

GLfloat coords[4][2];
if (info->r90) {
    coords[0][0] = (info->x + info->width) / textureWidth;
    coords[0][1] = info->y / textureHeight;

    coords[1][0] = info->x / textureWidth;
    coords[1][1] = info->y / textureHeight;

    coords[2][0] = (info->x + info->width) / textureWidth;
    coords[2][1] = (info->y + info->height) / textureHeight;

    coords[3][0] = info->x / textureWidth;
    coords[3][1] = (info->y + info->height) / textureHeight;
} else {
    coords[0][0] = info->x / textureWidth;
    coords[0][1] = info->y / textureHeight;

    coords[1][0] = info->x / textureWidth;
    coords[1][1] = (info->y + info->height) / textureHeight;

    coords[2][0] = (info->x + info->width) / textureWidth;
    coords[2][1] = info->y / textureHeight;

    coords[3][0] = (info->x + info->width) / textureWidth;
    coords[3][1] = (info->y + info->height) / textureHeight;
}
glBindBuffer(GL_ARRAY_BUFFER, info->texCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), coords, GL_STATIC_DRAW);
glEnableVertexAttribArray(spritesheet.attribTexCoord);
glVertexAttribPointer(spritesheet.attribTexCoord, 2, GL_FLOAT, GL_FALSE, 0, NULL);

With SFML, I want to do something like this:

sf::Sprite sprite;
sprite.setTexture(spritesheet);
sprite.setTextureRect(sf::IntRect(info->x, info->y, info->width, info->height), info->r90 ? sf::Clockwise90 : sf::NoRotation);

So SFML would check the second parameter which might inform it to set slightly different UV coords taking into account this rotation.

Alternate API could be
sprite.setTextureRectRotation(sf::Clockwise90)
.

Another alternative would simply be making updateTexCoords public instead of private.

I looked into SFML's code and it looks very clean and understandable. I would be happy to implement this feature. What I want to know is, are you interested in this feature? Should I make a pull request?
« Last Edit: August 06, 2014, 04:50:46 pm by superjoe »

Peteck

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
Re: ability to use rotated images with setTextureRect
« Reply #1 on: August 06, 2014, 04:54:22 pm »
One could just make a rotation calculation on the coordinates or just get the new coordinates from the packed texture. In my opinion its better to use the right coordinates than start rotating them to get right ones. But of course, its not up to me to make that decision.

superjoe

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: ability to use rotated images with setTextureRect
« Reply #2 on: August 06, 2014, 04:57:53 pm »
One could just make a rotation calculation on the coordinates or just get the new coordinates from the packed texture. In my opinion its better to use the right coordinates than start rotating them to get right ones. But of course, its not up to me to make that decision.

I don't think I'm communicating clearly. Consider a spritesheet like this:



Note that it has images that are normal and also images that are rotated 90 degrees. This is to make the spritesheet more efficient.

So I'm not using "wrong" coordinates. I'm using efficient texture packing, and it's easy to read the image from the texture in the correct orientation by adjusting the UV coords.

SFML just needs to let me call updateTexCoords manually or provide an API that understands rotation.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: ability to use rotated images with setTextureRect
« Reply #3 on: August 06, 2014, 05:29:42 pm »
You want to access rotated images to provide unrotated textures? Seems like a reasonable and common thing to need.
I'm not sure I fully understood but were you saying that OpenGL already provides this feature but SFML blocks it?

I suppose it's always possible to unpack them and repack them (without rotation) for your project although this sounds cumbersome.
I also suppose you could use sf::Image and copy and rotate the parts that you need but that seems like unnecessary work.
 ???

The other option is of course to modify SFML source for yourself but that doesn't help anyone else...
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

superjoe

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: ability to use rotated images with setTextureRect
« Reply #4 on: August 06, 2014, 05:57:14 pm »
The other option is of course to modify SFML source for yourself but that doesn't help anyone else...

I'm happy to submit a patch. This feature would be straightforward to write and small. I only want the blessing of the project leader(s) that they agree with the feature.

Peteck

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
Re: ability to use rotated images with setTextureRect
« Reply #5 on: August 06, 2014, 05:59:01 pm »
Hmm there are some problems by making this rotation function. First of all, what point should it rotate around? Lets say that it should just rotate around the center. If you then say the coordinates are like this

x: 0, y: 0, width: 50, height 25

When rotating this around the center you will get a wrong x coordinates outside the texture.

superjoe

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: ability to use rotated images with setTextureRect
« Reply #6 on: August 06, 2014, 06:21:33 pm »
Hmm there are some problems by making this rotation function. First of all, what point should it rotate around? Lets say that it should just rotate around the center. If you then say the coordinates are like this

x: 0, y: 0, width: 50, height 25

When rotating this around the center you will get a wrong x coordinates outside the texture.

There's no problem here. Don't think of it like a rotation point, think of it as simply storing the image sideways. It's just a matter of different UV coords. Example from SFML:

Before:


void Sprite::updateTexCoords()
{
    float left   = static_cast<float>(m_textureRect.left);
    float right  = left + m_textureRect.width;
    float top    = static_cast<float>(m_textureRect.top);
    float bottom = top + m_textureRect.height;

    m_vertices[0].texCoords = Vector2f(left, top);
    m_vertices[1].texCoords = Vector2f(left, bottom);
    m_vertices[2].texCoords = Vector2f(right, top);
    m_vertices[3].texCoords = Vector2f(right, bottom);
}

After:

void Sprite::updateTexCoords()
{
    float left   = static_cast<float>(m_textureRect.left);
    float right  = left + m_textureRect.width;
    float top    = static_cast<float>(m_textureRect.top);
    float bottom = top + m_textureRect.height;

    if (r90) {
      m_vertices[0].texCoords = Vector2f(right, top);
      m_vertices[1].texCoords = Vector2f(left, top);
      m_vertices[2].texCoords = Vector2f(right, bottom);
      m_vertices[3].texCoords = Vector2f(left, bottom);
    } else {
      m_vertices[0].texCoords = Vector2f(left, top);
      m_vertices[1].texCoords = Vector2f(left, bottom);
      m_vertices[2].texCoords = Vector2f(right, top);
      m_vertices[3].texCoords = Vector2f(right, bottom);
    }
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: ability to use rotated images with setTextureRect
« Reply #7 on: August 06, 2014, 06:25:53 pm »
Indeed, this feature would be easy to implement and your use case is relevant. Now we need to see whether we want it, and what API we would expose.

Personnally, I have no strong argument against it.

PS: your implementation is incomplete, the vertices' positions need to be adjusted as well.
« Last Edit: August 06, 2014, 06:27:47 pm by Laurent »
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: ability to use rotated images with setTextureRect
« Reply #8 on: August 06, 2014, 06:48:18 pm »
What speaks against providing a
setTextureRect(int left, int top, int right, int bottom);
overload in addition to the sf::IntRect one?

By breaking up the coordinates, we won't have to assume that the source texture rectangle always has the same orientation. Rotations could be expressed solely through manipulation of those coordinates. What's more: even mirroring along any axes could be expressed through manipulation of those coordinates and wouldn't force the user to rely on a non-trivial setScale() with a negative value which might even break other things.

The sf::Sprite would store those ints instead of the oriented sf::IntRect which doesn't even change it's size. This wouldn't break existing code either.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: ability to use rotated images with setTextureRect
« Reply #9 on: August 06, 2014, 06:50:37 pm »
How can you specify a rotated rectangle with (left, top, right, bottom)? ???
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: ability to use rotated images with setTextureRect
« Reply #10 on: August 06, 2014, 06:59:36 pm »
Hmm yeah... I realized what I actually meant were points instead of single values :P.

setTextureRect(const sf::Vector2i& leftTop, const sf::Vector2i& rightTop, const sf::Vector2i& rightBottom, const sf::Vector2i& leftBottom);

This provides more flexibility than most people might need... being able even to skew images etc. for whatever reason there might be.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

minirop

  • Sr. Member
  • ****
  • Posts: 254
    • View Profile
    • http://dev.peyj.com
Re: ability to use rotated images with setTextureRect
« Reply #11 on: August 06, 2014, 07:01:26 pm »
probably with having, let say, top/left being the top right corner and a negative width and let SFML do the work (for a 90 CW rotation) but probably too much hassle.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: ability to use rotated images with setTextureRect
« Reply #12 on: August 06, 2014, 07:12:42 pm »
Quote
Hmm yeah... I realized what I actually meant were points instead of single values
Maybe this is too much? I think it would considerably complicate the implementation of other functions, as well as the overall API of the sf::Sprite class.
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: ability to use rotated images with setTextureRect
« Reply #13 on: August 06, 2014, 07:28:38 pm »
I think it would considerably complicate the implementation of other functions
Not really... I just checked and there aren't that many places where the textureRect is actually accessed. Setting the textureRect and texture as well as bounds calculation.

as well as the overall API of the sf::Sprite class
This would only add 1 additional overload to the sf::Sprite class. getTextureRect would still return an oriented rectangle computed from the points.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: ability to use rotated images with setTextureRect
« Reply #14 on: August 06, 2014, 11:21:45 pm »
A getTextureRect() function doesn't make sense anymore if we can give 4 arbitrary pairs of texture coordinates. We would have to return something similar to what we can set, i.e. the 4 pairs of texture coordinates. A simple texture rect can still be retrieved with getLocal/GlobalBounds().

And what about shapes? If we go this way, there's no reason to limit shape texturing to an AABB rectangle, we should be able to set each point's texture coordinates as well.

That's what I have in mind when I say that the API would be more complicated.

Now for the implementation... sf::Sprite's local geometry is directly deduced from the texture rectangle. What if now we can set any shape composed of 4 points? The sprite will no longer be a quad.
Laurent Gomila - SFML developer