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

Author Topic: sf::Sprite rotate(45) bug  (Read 3694 times)

0 Members and 1 Guest are viewing this topic.

Foaly

  • Sr. Member
  • ****
  • Posts: 453
    • View Profile
sf::Sprite rotate(45) bug
« on: January 14, 2013, 06:58:50 pm »
While testing my AnimatedSprite class i noticed something weird. First I though it was something on my end, but after playing around a little more I noticed, that the sf::Sprite class has the same problem... (which makes sense, because I use the same code for calculating the texture coordinates)
Whenever I use the setTextureRect() member of a sprite and the left member is set to something other then the left border of the texture and I then rotate the sprite by 45 degrees the texture is offset by one pixel. Whether I use rotate or setRotation doesn't make a difference. This only happens with 45 or -45 or multiples of them (i.e.: 405, 765 etc.). This seems very weird to me, because the sf::Transform should not affect the texture coordinates, should it? It only affects the vertices, right?
Only thing I can think of, that might explain it, is that there is a float rounding error in updateTexCoords().

If the above makes no sense at all, then try this minimal example:
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(500, 500), "Rotate Test");

    sf::Texture texture;
    texture.loadFromFile("Rotate.png");

    sf::Sprite sprite;
    sprite.setTexture(texture);
    sprite.setPosition(200, 200);
    sprite.setTextureRect(sf::IntRect(1, 1, 98, 98));
    sprite.rotate(45);

    sf::Event event;

    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
                window.close();
        }

        window.clear();
        window.draw(sprite);
        window.display();
    }

    return 0;
}
 

with this image:

Rotated by 45° it looks like this:

The red boarder only appears when rotated by 45° any other angle works fine.

Can somebody else confirm this? I am using Windows 7 x64, a Geforce GTX 500 Ti, the latest source compiled with MinGW (gcc 4.7.2)

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: sf::Sprite rotate(45) bug
« Reply #1 on: January 14, 2013, 07:14:15 pm »
Can somebody else confirm this? I am using Windows 7 x64, a Geforce GTX 500 Ti, the latest source compiled with MinGW (gcc 4.7.2)
I can't with Windows 8 x64, Radeon HD 6470M, MinGW (GCC 4.7.2) - latest source.



And your graphics card driver is up-to-date, right?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: sf::Sprite rotate(45) bug
« Reply #2 on: January 14, 2013, 07:45:07 pm »
Happens for me, seems like opengl rasterizer problem similar to vertex array ones, setting origin to 0.5,0.5 helps, then the sprite is roated around it's top left pixel, not it's top left corner.
Back to C++ gamedev with SFML in May 2023

Foaly

  • Sr. Member
  • ****
  • Posts: 453
    • View Profile
Re: sf::Sprite rotate(45) bug
« Reply #3 on: January 14, 2013, 08:10:00 pm »
Yes my drivers are up to date. I'm using version 310.90.
Yep I can confirm that sprite.setOrigin(0.5, 0.5); fixes the problem. This doesn't seem like a clean solution though...
I did some testing and I think my theory was right. If i change the updateTexCoords() function to this:
void Sprite::updateTexCoords()
{
    float left = static_cast<float>(m_textureRect.left) + 0.0001;
    float right = left + m_textureRect.width;
    float top = static_cast<float>(m_textureRect.top) + 0.0001;
    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, bottom);
    m_vertices[3].texCoords = Vector2f(right, top);
}
Everything works as expected. I haven't checked if the position is still correct though...

Foaly

  • Sr. Member
  • ****
  • Posts: 453
    • View Profile
Re: sf::Sprite rotate(45) bug
« Reply #4 on: January 14, 2013, 08:55:42 pm »
Alright I did a quick test and the position of the sprite does not change whether you add a small float or not.
I also found out that
float left = static_cast<float>(rect.left) + 0.0001;
is enough to fix the problem. So i guess this might be the fix. Maybe somebody who doesn't have the problem could double check, if the fix doesn't break anything.

Foaly

  • Sr. Member
  • ****
  • Posts: 453
    • View Profile
Re: sf::Sprite rotate(45) bug
« Reply #5 on: January 17, 2013, 07:57:44 pm »
Nobody? :( Please, could somebody check?

I really think this fix should be added to the codebase, because it fixes what's obviously a bug on Nvidia graphics cards.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: sf::Sprite rotate(45) bug
« Reply #6 on: January 17, 2013, 08:51:46 pm »
Using your code, I can reproduce the red border. The problem is not related to rotating, it appears also with
sprite.move(0.5f, 0.f);

I have reported the bug long ago, it is indeed annoying. But I don't know if there is a clean and general solution.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Foaly

  • Sr. Member
  • ****
  • Posts: 453
    • View Profile
Re: sf::Sprite rotate(45) bug
« Reply #7 on: January 17, 2013, 09:43:47 pm »
Really? That's odd...
Using the current SFML source and sprite.move(0.5f, 0.f); the problem also occurs for me, but using my code ( + 0.0001 ) fixes it... have you actually tested it?

Weeve

  • Jr. Member
  • **
  • Posts: 87
  • C++ Programmer (Intermediate), 3D Artist (Skilled)
    • View Profile
    • Email
Re: sf::Sprite rotate(45) bug
« Reply #8 on: January 19, 2013, 09:41:28 pm »
changing the position by +0.0001 is not clean(because it requires an addition, where efficiency could be concerned), and it may fix that one function, but likely it is deeper into some rendering code (so thus not a general fix, but more of a patch), you could Fork SFML, then see how deep the actual issue is, fix it, and report your fix to the forums, or a mod, along with a description of why it was breaking ;) . that is, if your worrying that much about it. if I had a guess, NVidia counts pixels by their centre position, whereas other cards count pixels by corner position when managing floats. there's your first lead ;D
Long live rapid project development! -- Kestrel3D Game-Engine nearing completion