How to make rounded rectangle in OpenGL, or any polygon with rounded corners?
I needed to draw similar rectangle, but transparent - and code above draws some of triangles overlap. Fixed that, also removed malloc, just to simplify solution. Here is my version:
typedef struct
{
float x;
float y;
} Vector2f;
//
// Draws rounded rectangle.
//
// Slightly tuned version of http://stackoverflow.com/questions/5369507/opengles-1-0-2d-rounded-rectangle
//
#define ROUNDING_POINT_COUNT 8 // Larger values makes circle smoother.
void DrawRoundRect( float x, float y, float width, float height, float* color = 0, float radius = 0.0 )
{
Vector2f top_left[ROUNDING_POINT_COUNT];
Vector2f bottom_left[ROUNDING_POINT_COUNT];
Vector2f top_right[ROUNDING_POINT_COUNT];
Vector2f bottom_right[ROUNDING_POINT_COUNT];
if( radius == 0.0 )
{
radius = min(width, height);
radius *= 0.10; // 10%
}
int i = 0;
float x_offset, y_offset;
float step = ( 2.0f * pi ) / (ROUNDING_POINT_COUNT * 4),
angle = 0.0f;
unsigned int index = 0, segment_count = ROUNDING_POINT_COUNT;
Vector2f bottom_left_corner = { x + radius, y - height + radius };
while( i != segment_count )
{
x_offset = cosf( angle );
y_offset = sinf( angle );
top_left[ index ].x = bottom_left_corner.x -
( x_offset * radius );
top_left[ index ].y = ( height - ( radius * 2.0f ) ) +
bottom_left_corner.y -
( y_offset * radius );
top_right[ index ].x = ( width - ( radius * 2.0f ) ) +
bottom_left_corner.x +
( x_offset * radius );
top_right[ index ].y = ( height - ( radius * 2.0f ) ) +
bottom_left_corner.y -
( y_offset * radius );
bottom_right[ index ].x = ( width - ( radius * 2.0f ) ) +
bottom_left_corner.x +
( x_offset * radius );
bottom_right[ index ].y = bottom_left_corner.y +
( y_offset * radius );
bottom_left[ index ].x = bottom_left_corner.x -
( x_offset * radius );
bottom_left[ index ].y = bottom_left_corner.y +
( y_offset * radius );
top_left[ index ].x = top_left[ index ].x;
top_left[ index ].y = top_left[ index ].y;
top_right[ index ].x = top_right[ index ].x;
top_right[ index ].y = top_right[ index ].y;
bottom_right[ index ].x = bottom_right[ index ].x ;
bottom_right[ index ].y = bottom_right[ index ].y;
bottom_left[ index ].x = bottom_left[ index ].x ;
bottom_left[ index ].y = bottom_left[ index ].y ;
angle -= step;
++index;
++i;
}
static GLubyte clr[] = { 156, 207, 255, 128 }; // Light blue, 50% transparent.
if( color )
glColor4fv(color);
else
glColor4ubv(clr);
glBegin( GL_TRIANGLE_STRIP );
{
// Top
for( i = segment_count - 1 ; i >= 0 ; i--)
{
glVertex2f( top_left[ i ].x, top_left[ i ].y );
glVertex2f( top_right[ i ].x, top_right[ i ].y );
}
// In order to stop and restart the strip.
glVertex2f( top_right[ 0 ].x, top_right[ 0 ].y );
glVertex2f( top_right[ 0 ].x, top_right[ 0 ].y );
// Center
glVertex2f( top_right[ 0 ].x, top_right[ 0 ].y );
glVertex2f( top_left[ 0 ].x, top_left[ 0 ].y );
glVertex2f( bottom_right[ 0 ].x, bottom_right[ 0 ].y );
glVertex2f( bottom_left[ 0 ].x, bottom_left[ 0 ].y );
// Bottom
for( i = 0; i != segment_count ; i++ )
{
glVertex2f( bottom_right[ i ].x, bottom_right[ i ].y );
glVertex2f( bottom_left[ i ].x, bottom_left[ i ].y );
}
}
glEnd();
} //DrawRoundRect