30. OpenGL Circle Drawing (Version 2.0)

Introduction

In OpenGL, there is no predefined function to draw a perfect circle. However, we can create one by approximating it with a series of connected line segments. This tutorial will walk you through creating a custom function to generate circles using basic trigonometric functions and OpenGL commands.

We’ll also explore how to adjust the circle’s position, size, and smoothness by modifying its parameters.

Defining a Circle

To represent a circle in our program, we’ll use a simple struct to hold the x and y coordinates of each point on the circle:

typedef struct {
    float x; // X-coordinate of the point
    float y; // Y-coordinate of the point
} CIRCLE;

CIRCLE circle; // Declare a variable of type CIRCLE

Creating the Circle

The core of this tutorial lies in the createcircle function. This function generates a circle by calculating the coordinates of points along its circumference using trigonometric functions.

The function takes three parameters:

  • k: Translation along the y-axis.
  • r: Radius of the circle.
  • h: Translation along the x-axis.

Here’s the implementation:

void createcircle(int k, int r, int h) {
    const int segments = 180;
    const float pi = 3.14159265358979323846f;

    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < segments; ++i) {
        const float angle = 2.0f * pi * static_cast<float>(i) / static_cast<float>(segments);

        circle.x = h + r * std::cos(angle);
        circle.y = k + r * std::sin(angle);

        glVertex3f(circle.x, circle.y, 0.0f);
    }
    glEnd();
}

Understanding the Math

To compute the points along the circle, we use trigonometry:

  • The x-coordinate of a point is calculated as:
    x = r \cdot \cos(\theta) + h
  • The y-coordinate of a point is calculated as:
    y = r \cdot \sin(\theta) + k

Here:

  • r is the radius of the circle.
  • θ is the angle in radians.
  • h and k are translations along the x-axis and y-axis, respectively.

Drawing Circles with Different Properties

To draw a circle, simply call the createcircle function and pass the desired parameters. For example:

createcircle(0, 10, 0); // Circle centered at (0, 0) with radius 10

You can modify the parameters to change the circle’s position and size:

  • Increase r for a larger circle.
  • Adjust h and k to translate the circle horizontally and vertically.

Adding Multiple Circles

You can use the createcircle function to draw multiple circles with different properties. For instance:

glColor3f(1, 0, 0); // Set colour to red
createcircle(0, 10, 0);

glColor3f(0, 1, 0); // Set colour to green
createcircle(-2, 8, -2);

glColor3f(0, 0, 1); // Set colour to blue
createcircle(2, 4, 2);

Full Program

Here’s the complete implementation, including rendering multiple circles and animating them:

#include <GL/gl.h>
#include <GL/glut.h>
#include <cmath>

typedef struct {
    float x;
    float y;
} CIRCLE;

CIRCLE circle;
float rot = 0;

void createcircle(int k, int r, int h) {
    const int segments = 180;
    const float pi = 3.14159265358979323846f;

    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < segments; ++i) {
        const float angle = 2.0f * pi * static_cast<float>(i) / static_cast<float>(segments);

        circle.x = h + r * std::cos(angle);
        circle.y = k + r * std::sin(angle);

        glVertex3f(circle.x, circle.y, 0.0f);
    }
    glEnd();
}

void display(void) {
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0, 0, -20);

    glRotatef(rot, 0, 1, 0);
    glColor3f(1, 1, 1);
    createcircle(0, 10, 0);

    glColor3f(1, 0, 0);
    createcircle(-2, 8, -2);

    glColor3f(0, 1, 0);
    createcircle(-1, 6, -1);

    glColor3f(0, 0, 1);
    createcircle(2, 4, 2);

    glColor3f(0, 1, 1);
    createcircle(1, 2, 1);

    glutSwapBuffers();
    rot++;
}

void reshape(int w, int h) {
    if (h == 0) h = 1;
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60, (GLfloat)w / (GLfloat)h, 0.1, 100.0);
    glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("OpenGL Circle Drawing");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

Source & downloads

Questions or corrections? If something doesn’t work or you spot something I’ve got wrong, leave a comment below. These tutorials have been around a long time, so useful corrections are always welcome!

  • March 25, 2010
  • 15