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

Author Topic: Sprite clipping not working correctly (HD 2500)  (Read 3147 times)

0 Members and 1 Guest are viewing this topic.

Valmond

  • Newbie
  • *
  • Posts: 5
    • View Profile
Sprite clipping not working correctly (HD 2500)
« on: December 02, 2018, 12:23:02 am »
Hi everybody!

I have a small issue which is that when I draw a sprite with a negative position (in x or y), then it is not clipped (which it should as it's partially outside of the screen), but not drawn at all.

If I move the sprite to the right or downwards enough, so that the image is drawn "half outside" the window, then it works (the image is drawn but clipped by the physical window). But moving up or to the left, the sprite just pops out of existence as soon as x or y goes below zero.

Is this known / normal behavior / a HD2500 bug / other?

BTW I'm on Linux Mint, with a i3 3320 that has inbuilt HD 2500 graphics.

Thank you for any kind of help!

Cheers

Valmond

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite clipping not working correctly (HD 2500)
« Reply #1 on: December 02, 2018, 10:36:02 am »
Please provide a complete and minimal example that reproduces the problem.
Laurent Gomila - SFML developer

Valmond

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Sprite clipping not working correctly (HD 2500)
« Reply #2 on: December 02, 2018, 01:10:13 pm »
Hi, here is a small example, the bug appears when getSize is used in the setPos call...
The image used is a png with the size of 80x92 pixels


#include <SFML/Graphics.hpp>

int main()
{
    // Create the main window
    sf::RenderWindow app(sf::VideoMode(800, 600), "Test");

    // Load a sprite to display
    sf::Texture t1;
    if (!t1.loadFromFile("../media/gfx/ball.png"))return EXIT_FAILURE;
    sf::Sprite s1(t1);
       
        // Start the game loop
    while (app.isOpen())
    {
        // Process events
        sf::Event event;
        while (app.pollEvent(event))
        {
            // Close window : exit
            if (event.type == sf::Event::Closed)
                app.close();
        }

        // Clear screen
        app.clear();

        // Draw the sprites
               
                //just loop from 150 to 50 over and over so the sprite moves out of screen
                static float pp=150;
                pp=pp-.03f;
                if(pp<50)pp=150;

                //Here is the bug, if I don't use the t1.getSize().y in the function call, it works
                //Bug
                s1.setPosition(100-t1.getSize().x/2,-t1.getSize().y+(int)pp);
                app.draw(s1);
               
                //works
                int t=t1.getSize().y;
                s1.setPosition(300-t1.getSize().x/2,-t+(int)pp);
                app.draw(s1);
               
        // Update the window
        app.display();
    }

    return EXIT_SUCCESS;
}

 
« Last Edit: December 02, 2018, 02:25:38 pm by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite clipping not working correctly (HD 2500)
« Reply #3 on: December 02, 2018, 02:27:42 pm »
Have you tried to print the result of "-t1.getSize().y+(int)pp"?
Laurent Gomila - SFML developer

Valmond

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Sprite clipping not working correctly (HD 2500)
« Reply #4 on: December 02, 2018, 06:01:04 pm »
Well that would make no sense, as if I assign it to a variable before the setPosition call, it works.

I'm all new to SFML so I don't have the debug binaries. But for someone that can build SFML and debug in the SFML code, I think they could figure out the problem.

I'm work-arounding by first collecting the size, then call the setPosition, which is okay for me. Maybe there is a bugtracker somewhere where I can assign this?

texus

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • TGUI
    • Email
Re: Sprite clipping not working correctly (HD 2500)
« Reply #5 on: December 02, 2018, 06:23:19 pm »
The getSize().y has type "unsigned int". Adding it to an "int" still results in an "unsigned int" here.

The following code should print a very high number:
std::cout << -t1.getSize().y+(int)pp << std::endl;

For the very same reason that the following prints a large number. An "unsigned int" doesn't just become an "int" by putting a "-" in front of it.
unsigned u = 600;
std::cout << -u << std::endl;

When you created the temporary value you probably used type "int" so you were first casting the result to an "int" (which becomes the number you expected since the value of the "unsigned int" was too large to be represented in an "int"). In this case you would be converting the negative number to a float (which is what happens when calling setPosition since its parameters are floats). If you put "-t1.getSize().y+(int)pp" directly in setPosition then it instead converts the very large number to a float, placing the sprite far outside your screen.

The following code should thus work:
s1.setPosition(100-int(t1.getSize().x)/2,-int(t1.getSize().y)+(int)pp);
« Last Edit: December 02, 2018, 06:25:08 pm by texus »
TGUI: C++ SFML GUI

Valmond

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Sprite clipping not working correctly (HD 2500)
« Reply #6 on: December 02, 2018, 09:20:10 pm »
Ouch, thank you for this detailed answer!

Question closed then. Remains why ever someone would use an unsigned integer for this kind of data :-)

I know, it might seem logic, but signed ints everywhere would have prevented this, and added the bonus of being able to have negative sized images (e.g flipped).

Anyway, thanks again and I can now remove one line per draw call and just make a cast :-)

Cheers

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Sprite clipping not working correctly (HD 2500)
« Reply #7 on: December 02, 2018, 10:01:33 pm »
Because for a texture size it makes sense it'll never be negative and if it's 0 then it's an error.

An up to date Visual Studio 2017 actually wouldn't let me compile your code due to unary minus on unsigned which it treats like an error but GCC and Clang both don't warn about it with even -Wall and -Wextra, all these three facts are astonishing to me (GCC and Clang for not warning at all about it and forcing a cast and VS for marking this as an error and not just a warning).

Unsigned is sometimes avoided because of:

1. Optimization - unsigned has well defined overflow behavior, signed doesn't so supposedly it can be reasoned by a compiler that it'll never go above 2^(bits/2)-1 in a for loop and so on.

2. Some sort of compatibility, e.g. Java doesn't even have proper unsigned types, just some helper functions, C# (the language) has them but .NET doesn't since .NET is 'CLS compliant' which requires no use of unsigned since not all .NET languages need to have them (so List<T> index[] and Count both use signed ints).

3. Cramming error codes or special values into a return value or argument of something in statically typed languages, e.g. many system functions on many OSes return -1 or negative for errors, in Lua if you want LUA_MULTRET (it's -1) values returned to you then it'll give you as many as it can (just saying a number fills empty spots with nil so you can't just say 999999 to get them all), file size for file that can't be accessed report -1 in PHYSFS (game filesystem library in C) and LCL fileutils (a Free Pascal GUI and utils library).

Places where unsigned is used sometimes get around the last use by saying the maximum possible value has special meaning, like std::string::find returns std::string::npos which is just that too. An easy way to get maximum value of an unsigned type is to assign/cast -1 to it, which is why it astonishes me that VS2017 marks -1u as an error in its default settings, I can get it for variables but for a constant (or at least for -1u which is a common idiom, just like how integer 0 is treated specially and plainly assignable to pointers but other integers aren't) I'd expect it to pass and not require pragmas disabling warnings and errors (than again they also deprecate and fail to compile stuff like sprintf by default).

And of course for various crypto or bitwise work people use unsigned (and Java uses int or long and special functions that manipulate it or just relies on the fact Java mandates twos complement for its signed ints). I'm personally not sure which approach (unsigned because it makes sense vs signed because it's useful and has no gotchas) I like more and I keep changing my mind but leaning towards ints usually, even Stoustrup apparently said to not use unsigned unless you have a specific need (and I totally agree with Sutter's point and think that needing a size of something on the order of 2^63 is so insane and beyond capacities of entire data centers, let alone single files, that at that level a single bit doesn't make or break you and you'll get caught by something else anyway like adding sizes of two such files overflowing even unsigned 64 bit): https://www.nayuki.io/page/unsigned-int-considered-harmful-for-java
« Last Edit: December 02, 2018, 10:23:33 pm by FRex »
Back to C++ gamedev with SFML in May 2023

Valmond

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Sprite clipping not working correctly (HD 2500)
« Reply #8 on: December 02, 2018, 11:44:29 pm »
Hah, I had to read it all just to understand your viewpoint (uint good or bad) :-)

Yes, in my opinion too, signed integers is the way to go, and as you pointed out, SFML is not for impossibly big images (I work with TB sized 3D data, we use signed ints when we don't use floats, which are signed too of course).

But the most important IMO is that unsigned ints make pesky bugs like this where it could have been avoided.
Now I know about this particularity, but lots of others might try to check out SFML and just think it's broken or give up or annoy people on the forum :-).

+1 from me

Cheers

Valmond

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Sprite clipping not working correctly (HD 2500)
« Reply #9 on: December 03, 2018, 01:44:57 am »
Yes, other than special uses I only have the vague "make sense" feeling and I like to be lazy and check only x < max, not 0 < x and x < max in my own code, so I usually lean (other than when lazy or feeling idealistic or avoiding warnings from STL) to ints for consistency and all their benefits. I'm surprised that despite them seeing the misleading expression in its entirety there is no warning from either Clang or GCC while VS just outright refuses to compile it or even -1u.

Any situation where uint is a benefit is quickly derailed too IMO, e.g. this bit of code I wrote recently (tsize and fsize are int64) for Botes (last link in my under-post forum description, yes, I shill it):
list := FindAllFiles(oname);
tsize := 0;
for fname in list do
begin
  fsize := FileSize(fname);
  if fsize > 0 then
    tsize += fsize;
end;

Even if FileSize returned a uin64 (forcing me to call another function to check if file exists first or catch an exception instead of knowing I get -1, for the never important in reality benefit of supporting up to 16 EiB files instead of 'just' 8 EiB) and I used all uint64 then at that scale (files on the order of several EiB each) all bets are off since my summing up will overflow it anyway and make the program incorrect again.

Not to even mention what an insane scale that'd be for a single file or even machine, entire Backblaze backup company has 'only' few hundred PB total.
Back to C++ gamedev with SFML in May 2023