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

Author Topic: Weird problem with sf::Shape:getGlobalBounds() when using non rectangular shapes  (Read 3054 times)

0 Members and 1 Guest are viewing this topic.

Ricky

  • Jr. Member
  • **
  • Posts: 99
    • View Profile
    • Tejada
    • Email
Hello there!

I have been reworking my collision detection using sfml shapes but I've noticed an issue when getting global
bounding box from non rectangular shapes.

Here is a code sample that reproduces the problem. I commented out the rectangle code because it works, you can uncomment it and comment the triangle shape code to see for yourself the difference.

#include "sfml/graphics.hpp"

int main(void)
{
    sf::RenderWindow m_window(sf::VideoMode(640, 480, 32), "Test Convex Shape", sf::Style::Close);
    m_window.setVerticalSyncEnabled(true);
    sf::Event m_events;

    sf::ConvexShape m_shape;
    /*m_shape.setPointCount(4);
    m_shape.setPoint(0, sf::Vector2f(0, 0));
    m_shape.setPoint(1, sf::Vector2f(0, 32));
    m_shape.setPoint(2, sf::Vector2f(32, 32));
    m_shape.setPoint(3, sf::Vector2f(32, 0));*/


    m_shape.setPointCount(3);
    m_shape.setPoint(0, sf::Vector2f(0, 0));
    m_shape.setPoint(1, sf::Vector2f(0, 32));
    m_shape.setPoint(2, sf::Vector2f(32, 32));

    m_shape.setFillColor(sf::Color::Transparent);
    m_shape.setOutlineColor(sf::Color::Red);
    m_shape.setOutlineThickness(1);

    sf::RectangleShape m_rectangle;
    m_rectangle.setFillColor(sf::Color::Transparent);
    m_rectangle.setOutlineColor(sf::Color::Yellow);
    m_rectangle.setOutlineThickness(1);

    while(m_window.isOpen())
    {
        while(m_window.pollEvent(m_events))
        {
            switch(m_events.type)
            {
                case sf::Event::Closed:
                {
                    m_window.close();
                    break;
                }
                default:
                    break;
            }
        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            m_shape.move(0, -10);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            m_shape.move(0, 10);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            m_shape.move(-10, 0);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            m_shape.move(10, 0);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
            m_shape.rotate(10);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
            m_shape.rotate(-10);

        m_rectangle.setPosition(m_shape.getGlobalBounds().left, m_shape.getGlobalBounds().top);
        m_rectangle.setSize(sf::Vector2f(m_shape.getGlobalBounds().width, m_shape.getGlobalBounds().height));

        m_window.clear();
        m_window.draw(m_rectangle);
        m_window.draw(m_shape);
       

        m_window.display();
    }

    return false;
}

The getGlobalBounds() function should return the bounding space in global coords right? So why the extra space that is not part of the shape included?

Help greatly appreciated!
Wilt thou yet say before him that slayeth thee, I am God? but thou shalt be a man, and no God, in the hand of him that slayeth thee.

G.

  • Hero Member
  • *****
  • Posts: 1590
    • View Profile
It's weird but it's normal behavior. :/

#include <SFML/Graphics.hpp>
#include <iostream>

int main(void)
{
    sf::RenderWindow m_window(sf::VideoMode(640, 480, 32), "Test Convex Shape", sf::Style::Close);
    m_window.setVerticalSyncEnabled(true);
    sf::Event m_events;

    sf::ConvexShape m_shape;

    m_shape.setPointCount(3);
    m_shape.setPoint(0, sf::Vector2f(0, 0));
    m_shape.setPoint(1, sf::Vector2f(0, 32));
    m_shape.setPoint(2, sf::Vector2f(32, 32));

    m_shape.setFillColor(sf::Color::Transparent);
    m_shape.setOutlineColor(sf::Color::Red);
    m_shape.setOutlineThickness(1);

    sf::RectangleShape m_rectangle;
    m_rectangle.setFillColor(sf::Color::Transparent);
    m_rectangle.setOutlineColor(sf::Color::Yellow);
    m_rectangle.setOutlineThickness(1);
    m_rectangle.setSize(sf::Vector2f(m_shape.getLocalBounds().width, m_shape.getLocalBounds().height));

    sf::RectangleShape m_rectangle2;
    m_rectangle2.setFillColor(sf::Color::Transparent);
    m_rectangle2.setOutlineColor(sf::Color::Blue);
    m_rectangle2.setOutlineThickness(1);

    while(m_window.isOpen())
    {
        while(m_window.pollEvent(m_events))
        {
            switch(m_events.type)
            {
                case sf::Event::Closed:
                {
                    m_window.close();
                    break;
                }
                default:
                    break;
            }
        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            m_shape.move(0, -10);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            m_shape.move(0, 10);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            m_shape.move(-10, 0);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            m_shape.move(10, 0);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
            m_shape.rotate(10);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
            m_shape.rotate(-10);

        m_rectangle.setPosition(m_shape.getPosition().x, m_shape.getPosition().y);
        m_rectangle.setRotation(m_shape.getRotation());

        m_rectangle2.setPosition(m_shape.getGlobalBounds().left, m_shape.getGlobalBounds().top);
        m_rectangle2.setSize(sf::Vector2f(m_shape.getGlobalBounds().width, m_shape.getGlobalBounds().height));

        m_window.clear();
        m_window.draw(m_rectangle);
        m_window.draw(m_shape);
        m_window.draw(m_rectangle2);

        m_window.display();
    }

    return false;
}
« Last Edit: July 16, 2014, 07:21:57 pm by G. »

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Not related to your problem (sorry), but I just couldn't ignore that "return false;" in main().
Returning nothing is explicitly allowed by the standard and equates to "return 0;", so that would have been OK. Returning EXIT_SUCCESS or EXIT_FAILURE would also have been fine (and arguably slightly better than "return 0;" or "return 1;" although those would also pass). But returning "false" which is of type "bool" which is a completely different type than what main() returns (int) is just wrong. Don't do that!

Sorry about the rant and the fact that I'm not actually helping you with what you ask - I just couldn't let that pass without comment.

Ricky

  • Jr. Member
  • **
  • Posts: 99
    • View Profile
    • Tejada
    • Email
Quote
And don't forget that the global bounding rect is the transformed local bounding rect, not the bounding rect of the transformed points.

Welp, better write it myself.

Also thanks Jesper for catching my bad bad habits. Self teaching isn't perfect  ::)
Wilt thou yet say before him that slayeth thee, I am God? but thou shalt be a man, and no God, in the hand of him that slayeth thee.

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Here's a helpful illustration: http://en.sfml-dev.org/forums/index.php?topic=13673.msg95677#msg95677

Also: return 0 and return EXIT_SUCCESS is the same thing, return 1 and return EXIT_FAILURE is not (see 18.5.8 ). And bool and int have well defined conversions between each other (see 3.9.1.6, 4.7.4 and 4.12). return false is here same as return 0 (it's still very confusing to write that here but you can - for example - use bools with C code that uses ints as boolean values).
« Last Edit: July 16, 2014, 09:24:52 pm by FRex »
Back to C++ gamedev with SFML in May 2023

Ricky

  • Jr. Member
  • **
  • Posts: 99
    • View Profile
    • Tejada
    • Email
Here's a helpful illustration: http://en.sfml-dev.org/forums/index.php?topic=13673.msg95677#msg95677

Also: return 0 and return EXIT_SUCCESS is the same thing, return 1 and return EXIT_FAILURE is not (see 18.5.8 ). And bool and int have well defined conversions between each other (see 3.9.1.6, 4.7.4 and 4.12). return false is here same as return 0 (it's still very confusing to write that here but you can - for example - use bools with C code that uses ints as boolean values).

Thanks! I've decided to write my own function that gets the min and max values from the points in the shape to use as the top left corner and bottom right corner of the rectangle.

Also that bad habit of returning bools to the OS from main() is something I picked up in C..
Wilt thou yet say before him that slayeth thee, I am God? but thou shalt be a man, and no God, in the hand of him that slayeth thee.