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

Author Topic: Convex shape doesn't always provide correct globalbounds  (Read 4292 times)

0 Members and 1 Guest are viewing this topic.

The_Cleaner

  • Newbie
  • *
  • Posts: 9
    • View Profile
Convex shape doesn't always provide correct globalbounds
« on: May 07, 2012, 09:17:35 pm »
Not sure if this is a bug, or I'm doing something wrong here, but I'm stumped at the moment...
I've been working on some shape helpers and whenever I ask for globalbounds on a triangle with a 45 degree rotation, I get a larger bounding rect then I should be getting. It works fine for any 90 degree increment, but nothing in between (45 degrees is just an example).

Here is my main function, so you can reproduce the behavior.
What am I doing wrong here, or am I not understanding the getGlobalBounds() function?

thanks,

int main()
{
    sf::ConvexShape myTri(3);
    myTri.setPoint(0,sf::Vector2f(0,100));
    myTri.setPoint(1,sf::Vector2f(100,0));
    myTri.setPoint(2,sf::Vector2f(200,100));
    myTri.setFillColor(sf::Color::Black);
    myTri.setOrigin(100,50);
    myTri.rotate(45);

    sf::FloatRect bounds = myTri.getGlobalBounds();

    sf::RectangleShape myRect( sf::Vector2f(bounds.width, bounds.height) );

    myTri.move(bounds.width/2,bounds.height/2);


     sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML window");

     // Limit the framerate to 60 frames per second (this step is optional)
     window.setFramerateLimit(60);

     // The main loop - ends as soon as the window is closed
     while (window.isOpen())
     {
        // Event processing
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Request for closing the window
            if (event.type == sf::Event::Closed)
                window.close();
        }

        // Clear the whole window before rendering a new frame
        window.clear(sf::Color(0,0,255));

        // Draw some graphical entities
        window.draw(myRect);
        window.draw(myTri);

        // End the current frame and display its contents on screen
        window.display();
     }

    return 0;
}
 

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Re: Convex shape doesn't always provide correct globalbounds
« Reply #1 on: May 08, 2012, 08:31:28 am »
It's perfectly normal that the bounding box gets larger, as it's expanded to the corner points.

Compile this example and press R to rotate the triangle, it shows the effect pretty good:


#include <SFML/Graphics.hpp>

sf::RectangleShape make_bounding_box( const sf::FloatRect& rect ) {
        sf::RectangleShape bounding_box( sf::Vector2f( rect.width, rect.height ) );
        bounding_box.setFillColor( sf::Color::Transparent );
        bounding_box.setOutlineColor( sf::Color::Red );
        bounding_box.setOutlineThickness( 2.0f );

        bounding_box.setPosition( rect.left, rect.top );

        return bounding_box;
}

int main() {
        sf::RenderWindow window( sf::VideoMode( 800, 600 ), "GB" );
        sf::Event event;

        window.setFramerateLimit( 60 );

        sf::ConvexShape shape( 3 );
        shape.setPoint( 0, sf::Vector2f( 0.0f, 0.0f ) );
        shape.setPoint( 1, sf::Vector2f( 0.0f, 100.0f ) );
        shape.setPoint( 2, sf::Vector2f( 100.0f, 100.0f ) );
        shape.setFillColor( sf::Color::White );
        shape.setOutlineColor( sf::Color::Blue );
        shape.setOutlineThickness( 1.0f );

        shape.setPosition(
                static_cast<float>( window.getSize().x / 2.0f ) - shape.getGlobalBounds().left / 2.0f,
                static_cast<float>( window.getSize().y / 2.0f ) - shape.getGlobalBounds().top / 2.0f
        );

        shape.setOrigin( sf::Vector2f( 50.0f, 50.0f ) );

        sf::RectangleShape bounding_box = make_bounding_box( shape.getGlobalBounds() );

        float angle = 0.0f;
        sf::Clock frame_timer;

        while( window.isOpen() ) {
                sf::Time frametime = frame_timer.restart();

                while( window.pollEvent( event ) ) {
                        if( event.type == sf::Event::Closed ) {
                                window.close();
                        }
                }

                if( sf::Keyboard::isKeyPressed( sf::Keyboard::R ) ) {
                        angle += 90.0f * frametime.asSeconds();
                        shape.setRotation( angle );

                        bounding_box = make_bounding_box( shape.getGlobalBounds() );
                }

                window.clear();

                window.draw( shape );
                window.draw( bounding_box );

                window.display();
        }
}
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Convex shape doesn't always provide correct globalbounds
« Reply #2 on: May 08, 2012, 08:55:21 am »
And don't forget that the global bounding rect is the transformed local bounding rect, not the bounding rect of the transformed points.
Laurent Gomila - SFML developer

The_Cleaner

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Convex shape doesn't always provide correct globalbounds
« Reply #3 on: May 08, 2012, 01:43:05 pm »
Thanks for the reply,
Tank, this does clearly illustrate that this is expected, and Laurent, I see your point, that no funny business is done, it's just the local rect transformed, however, how would you get an accurate collision from the bounding rect in this case? I thought ultimately that was the point of a bounding rect... it looks to me that the rect is scaled uniformly, why not just scale it in x or y by what it needs? Will it break something else?

The_Cleaner

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Convex shape doesn't always provide correct globalbounds
« Reply #4 on: May 08, 2012, 02:51:40 pm »
Tank,
it also varies by the original orientation of the triangle and the dimensions, try it with these points for the triangle and see!

shape.setPoint( 0, sf::Vector2f( 0.0f, 100.0f ) );
shape.setPoint( 1, sf::Vector2f( 100.0f, 0.0f ) );
shape.setPoint( 2, sf::Vector2f( 200.0f, 100.0f ) );

The bounding rect is fine, and I'd expect the global to grow, just not as big as it is.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Convex shape doesn't always provide correct globalbounds
« Reply #5 on: May 08, 2012, 03:26:17 pm »
If you want an accurate bouding rect, you can transform the shape's points and recompute a better one from that.
Laurent Gomila - SFML developer

The_Cleaner

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Convex shape doesn't always provide correct globalbounds
« Reply #6 on: May 08, 2012, 04:20:48 pm »
Well I can certainly do that, I thought that would be the point of globalbounds, I cannot think of a use for them if I can't count on them to be relatively accurate. Mind you I'm not looking for a "I'll get right on it" answer or anything. I'm just seeing if you see it that way, or if I'm misinterpreting the purpose of globalbounds. That said, I'm sure I can work around this issue doing as you said Laurent, I just wanted to see if this is an issue or not. Sounds like not, judging from the previous post. But please enlighten me on the use of globalbounds if not for minor collision checking.

thanks again,
Ben

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Convex shape doesn't always provide correct globalbounds
« Reply #7 on: May 08, 2012, 04:34:09 pm »
The problem is that computing an accurate global bounding rect is expensive, and this process only makes sense if the entity is rotated. That's the reason why it's not the default in SFML.
Laurent Gomila - SFML developer

 

anything