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) {
    glBegin(GL_LINES); // Start drawing lines
    for (int i = 0; i < 180; i++) {
        // Calculate the first point
        circle.x = r * cos(i) - h;
        circle.y = r * sin(i) + k;
        glVertex3f(circle.x + k, circle.y - h, 0);

        // Calculate the second point (slightly offset)
        circle.x = r * cos(i + 0.1) - h;
        circle.y = r * sin(i + 0.1) + k;
        glVertex3f(circle.x + k, circle.y - h, 0);
    }
    glEnd(); // Finish drawing lines
}

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.
- \(\theta\) 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 color to red
createcircle(0, 10, 0);

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

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

Full Program

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

#include 
#include 
#include 

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

CIRCLE circle;
float rot = 0;

void createcircle(int k, int r, int h) {
    glBegin(GL_LINES);
    for (int i = 0; i < 180; i++) {
        circle.x = r * cos(i) - h;
        circle.y = r * sin(i) + k;
        glVertex3f(circle.x + k, circle.y - h, 0);

        circle.x = r * cos(i + 0.1) - h;
        circle.y = r * sin(i + 0.1) + k;
        glVertex3f(circle.x + k, circle.y - h, 0);
    }
    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) {
    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;
}

If you have any questions or need further assistance, feel free to email me at swiftless@gmail.com. Happy coding!

  • March 25, 2010
  • 15