SFML community forums

Help => Graphics => Topic started by: Syndog on November 23, 2013, 10:20:25 pm

Title: ConvexShape::getGlobalBounds() Problem
Post by: Syndog on November 23, 2013, 10:20:25 pm
Hello, SFML gurus.  :)

I've been kicking around with the ConvexShape class today, and came across something curious.  When I make a call to the ConvexShape::getGlobalBounds() method, it returns a FloatRect whose position and/or size seems to be flawed as the shape rotates.

Here's a simple program to demonstrate...

#include <SFML/Graphics.hpp>

using namespace sf;

int main() {
   RenderWindow window(VideoMode(800, 600), "Bounding Box Demo");

   ConvexShape arrow(4);
   arrow.setPosition(400.0f, 300.0f);
   arrow.setFillColor(Color::Blue);
   arrow.setOutlineColor(Color::Blue);
   arrow.setOutlineThickness(1.0f);
   arrow.setPoint(0, Vector2f(0, -20));
   arrow.setPoint(1, Vector2f(30, 60));
   arrow.setPoint(2, Vector2f(0, 40));
   arrow.setPoint(3, Vector2f(-30, 60));

   Vertex pivotPoint[1];
   pivotPoint[0].position.x = 400.0f;
   pivotPoint[0].position.y = 300.0f;
   pivotPoint[0].color = Color::Yellow;

   FloatRect bounds;
   RectangleShape boundingBox;

   Event event;

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

      window.clear(Color::Black);

      arrow.rotate(0.01f);

      bounds = arrow.getGlobalBounds();
      boundingBox.setPosition(Vector2f(bounds.left, bounds.top));
      boundingBox.setSize(Vector2f(bounds.width, bounds.height));

      window.draw(boundingBox, RenderStates::Default);
      window.draw(arrow, RenderStates::Default);
      window.draw(pivotPoint, 1, sf::PrimitiveType::Points, RenderStates::Default);

      window.display();
   }

   return 0;
}
 

If the arrow is rotated in any of the cardinal compass directions (0, 90, 180, 270 degrees) , the bounding box matches the vertices flawlessly.  However, as the arrow rotates, the bounding box grows increasingly inaccurate as it approaches the diagonal directions (45, 135, 225, 315 degrees), leaving a sizable gap around the arrow's tip, while remaining true to the two ends of the arrow's tail...


(https://dl.dropboxusercontent.com/u/63625202/temp/nogaps.gif)


(https://dl.dropboxusercontent.com/u/63625202/temp/gaps.gif)


I've tried running this using SFML 2.1, plus the latest source snapshot downloaded from the downloads page, and the same behavior persists.  I'm wondering if there's a problem with the ConvexShape::getGlobalBounds() method, or if perhaps I'm just misunderstanding what it's intended to provide.

Any insight would be greatly appreciated!

- Syn
Title: Re: ConvexShape::getGlobalBounds() Problem
Post by: FRex on November 23, 2013, 10:32:54 pm
That's normal because of way sf::Rect is translated and aligned to axes.
(http://oi40.tinypic.com/zk25j5.jpg)
Title: Re: ConvexShape::getGlobalBounds() Problem
Post by: Nexus on November 23, 2013, 10:35:31 pm
Additionally, your shape is not convex. The fact that it seems to work nevertheless is a side effect of the current implementation; that may change at any time.

If you need concave shapes, have a look at thor::ConcaveShape (http://www.bromeon.ch/libraries/thor/v2.0/doc/classthor_1_1_concave_shape.html).
Title: Re: ConvexShape::getGlobalBounds() Problem
Post by: Syndog on November 23, 2013, 10:42:36 pm
@FRex - Ahhh, understood.  Well, that makes it arguably less useful, but at least the behavior is explained.  Thanks for the illustration, it's most helpful!

@Nexus - In regards to the shape being concave, I refer you to the Shapes tutorial...

http://www.sfml-dev.org/tutorials/2.1/graphics-shape.php (http://www.sfml-dev.org/tutorials/2.1/graphics-shape.php)
Quote
Officially, sf::ConvexShape can only create convex shapes. But in fact, its requirements are a little more relaxed. In fact, the only technical constraint that your shape must follow, is that if you draw a line from its center of gravity to any of its point, you mustn't cross an edge. With this relaxed definition, you can for example draw stars.

The arrow's shape meets this criterion.
Title: Re: ConvexShape::getGlobalBounds() Problem
Post by: Nexus on November 24, 2013, 10:41:57 am
Ah you're right. I remembered a discussion (http://en.sfml-dev.org/forums/index.php?topic=3195.msg20802#msg20802) where Laurent stated this would be an implementation detail and shouldn't be considered a feature. Apparently he changed his opinion meanwhile ;)