SFML community forums

Help => Graphics => Topic started by: Astrof on January 28, 2009, 08:29:47 pm

Title: Rounded Rectangles
Post by: Astrof on January 28, 2009, 08:29:47 pm
I was wondering, does SFML have a way to do RoundedRectangles (with or without OpenGL)?  If not, would it be more efficient to use primitive shapes to kind of make a rounded rectangle or to use an image?

Just wondering, thanks!
Title: Rounded Rectangles
Post by: quasius on January 28, 2009, 10:57:27 pm
Use an image.  (You could have a small "round corner" image that you pair with straight line images as necessary.)
You could also do some stuff with alpha masks and texture combiners / shaders, but if you don't know about that stuff, piecing together the rectangles HTML-style for rounded corners should work.
Making a shape primitive with enough segments to appear round is probably not very efficient.
Title: Rounded Rectangles
Post by: Astrof on January 29, 2009, 03:47:48 pm
Just wondering, is there a way to edit the Circle to make this? (or is the circle rendered differently than other shapes?)  Basically I am wondering how the circle itself is drawn and also if its possible to maybe take the circle, split it, and add lines (for the rectangle part) .  Does that even make sense?
Title: Rounded Rectangles
Post by: Laurent on January 29, 2009, 04:32:33 pm
The circle is a regular shape, the Shape::Circle function just computes the points to build it. But you won't be able to modify it, as the list of points has to remain in order, and define a convex shape. Unless you copy them somewhere, insert your own points at the right locations in the list, and rebuild a shape from that.

You'd better create a sf::Shape RoundedRect(...) function which computes all the points directly.
Title: Rounded Rectangles
Post by: Astrof on February 14, 2009, 10:38:04 pm
Ok, so I (finally) made my own RoundedRectangle function.  Here are a few pics of what I have so far:

(http://ashwindec11.googlepages.com/RoundedRectangle.jpg)

this is just the RoundedRectangle

(http://ashwindec11.googlepages.com/RoundedRectangleWithRectangle.jpg)

This is a Rounded Rectangle along with a Rectangle (given the same Rectangle points).  
The radius of the arcs is 15.  I use 40 points total (same as sf::Shape::Circle).  For more or less accuracy you can edit the number of points (right now is a #define statement), but for some reason you can only have an even number (I do a for loop for each corner, so with an N of 10 there's 40 points total).

Can you believe it, I actually had to use Geometry on this... :roll:
Title: Rounded Rectangles
Post by: Tank on February 14, 2009, 11:09:51 pm
Looks good! Would be cool to see that in trunk. :)
Title: Rounded Rectangles
Post by: Astrof on February 15, 2009, 05:38:01 am
Here is the code (as a function):
Code: [Select]

#define POINTS 10
sf::Shape& RoundedRectangle(float x, float y, float rectWidth, float rectHeight, float radius, const sf::Color& Col, float Outline, const sf::Color& OutlineCol)
{
sf::Shape* rrect=new sf::Shape();
rrect->SetOutlineWidth(Outline);
float X=0,Y=0;
for(int i=0; i<POINTS; i++)
{
X+=radius/POINTS;
Y=sqrt(radius*radius-X*X);
rrect->AddPoint(X+x+rectWidth-radius,y-Y+radius,Col,OutlineCol);
}
Y=0;
for(int i=0; i<POINTS; i++)
{
Y+=radius/POINTS;
X=sqrt(radius*radius-Y*Y);
rrect->AddPoint(x+rectWidth+X-radius,y+rectHeight-radius+Y,Col,OutlineCol);
}
X=0;
for(int i=0; i<POINTS; i++)
{
X+=radius/POINTS;
Y=sqrt(radius*radius-X*X);
rrect->AddPoint(x+radius-X,y+rectHeight-radius+Y,Col,OutlineCol);
}
Y=0;
for(int i=0; i<POINTS; i++)
{
Y+=radius/POINTS;
X=sqrt(radius*radius-Y*Y);
rrect->AddPoint(x-X+radius,y+radius-Y,Col,OutlineCol);
}
return *rrect;

}

I don't know if it was the most efficient way to go about doing this, but this is how my mind worked when I was coding it.  If there is a way to make this code in any way better, I'd like to know; I'm fairly new to C++ (coming from Java).  Anyone is free to use this code, modify it, etc.
Title: Rounded Rectangles
Post by: Nexus on February 15, 2009, 11:00:47 am
You produce a nice memory leak. If you use new to allocate memory, you have to free it again by using delete.

But why don't you just create a sf::Shape on the stack?

Code: [Select]
// No reference but a copy is returned
sf::Shape RoundedRectangle(float x, float y, float rectWidth, float rectHeight, float radius, const sf::Color& Col, float Outline, const sf::Color& OutlineCol)
{
    sf::Shape rrect;    // creating a Shape - automatic storage class
    rrect.SetOutlineWidth(Outline);
    ...
    return rrect;
}

And please don't use #define for constants in C++. Either you declare a const int or add a further default-parameter which would make the whole thing more flexible.
Title: Rounded Rectangles
Post by: Astrof on February 15, 2009, 07:48:10 pm
Awesome, this is why I ask for help in my code ^_^.  I'll change that right away.  
I guess the reason why I did that is I don't like making copies of objects (always thought that it wasted more memory), but I guess it is deleted after I exit the function (and a memory leak is waaaay worse).

EDIT: ok, changed the function to:
Code: [Select]

sf::Shape RoundedRectangle(float x, float y, float rectWidth, float rectHeight, float radius, const sf::Color& Col, float Outline = 0.f, const sf::Color& OutlineCol = sf::Color(0, 0, 0), int POINTS=10);

the rest of the function is the same, just does not use a pointer.  
Thanks for the help!