31. OpenGL Sphere Creation (Version 2.0)

Introduction

Creating spheres in OpenGL is a fundamental task for rendering objects like planets or balls in 3D space. While GLUT offers built-in methods for sphere generation, they are limited in customisation, particularly when it comes to texture mapping. In this tutorial, we’ll learn how to create a textured sphere from scratch using custom calculations for vertices and texture coordinates.

By generating the sphere manually, we gain flexibility and control, allowing for applications like realistic Earth rendering, game objects, or scientific visualisation.

Setting Up Variables

Before we can generate our sphere, we need to define the necessary variables. These include:

// Stores the sphere's texture
GLuint texture[1];

// Angle of rotation for the sphere
double angle = 0;

// Vertex structure to store position and texture coordinates
typedef struct {
    float X, Y, Z;  // Vertex coordinates
    double U, V;    // Texture coordinates
} VERTICES;

// Constants for calculations
const double PI = 3.1415926535897; // Value of PI
const int space = 10;              // Angular step size for sphere segments
const int VertexCount = (90 / space) * (360 / space) * 4; // Total vertices
VERTICES VERTEX[VertexCount];      // Array to store sphere vertices

Creating the Sphere

The function CreateSphere is responsible for generating the vertices and texture coordinates of the sphere. It divides the sphere into latitude and longitude segments and calculates each point using trigonometric functions.

The function accepts four parameters:

  • R: Radius of the sphere.
  • H: Horizontal translation.
  • K: Vertical translation.
  • Z: Depth translation.
void CreateSphere(double R, double H, double K, double Z) {
    int n = 0; // Vertex counter
    for (double b = 0; b <= 90 - space; b += space) {
        for (double a = 0; a <= 360 - space; a += space) {
            // Vertex 1
            VERTEX[n].X = R * sin((a) / 180 * PI) * sin((b) / 180 * PI) - H;
            VERTEX[n].Y = R * cos((a) / 180 * PI) * sin((b) / 180 * PI) + K;
            VERTEX[n].Z = R * cos((b) / 180 * PI) - Z;
            VERTEX[n].U = (a) / 360;
            VERTEX[n].V = (2 * b) / 360;
            n++;

            // Vertex 2
            VERTEX[n].X = R * sin((a) / 180 * PI) * sin((b + space) / 180 * PI) - H;
            VERTEX[n].Y = R * cos((a) / 180 * PI) * sin((b + space) / 180 * PI) + K;
            VERTEX[n].Z = R * cos((b + space) / 180 * PI) - Z;
            VERTEX[n].U = (a) / 360;
            VERTEX[n].V = (2 * (b + space)) / 360;
            n++;

            // Vertex 3
            VERTEX[n].X = R * sin((a + space) / 180 * PI) * sin((b) / 180 * PI) - H;
            VERTEX[n].Y = R * cos((a + space) / 180 * PI) * sin((b) / 180 * PI) + K;
            VERTEX[n].Z = R * cos((b) / 180 * PI) - Z;
            VERTEX[n].U = (a + space) / 360;
            VERTEX[n].V = (2 * b) / 360;
            n++;

            // Vertex 4
            VERTEX[n].X = R * sin((a + space) / 180 * PI) * sin((b + space) / 180 * PI) - H;
            VERTEX[n].Y = R * cos((a + space) / 180 * PI) * sin((b + space) / 180 * PI) + K;
            VERTEX[n].Z = R * cos((b + space) / 180 * PI) - Z;
            VERTEX[n].U = (a + space) / 360;
            VERTEX[n].V = (2 * (b + space)) / 360;
            n++;
        }
    }
}

Rendering the Sphere

To render the sphere, we use OpenGL’s triangle strips and bind the texture to its surface. The DisplaySphere function handles this process:

void DisplaySphere(double R, GLuint texture) {
    glScalef(0.0125 * R, 0.0125 * R, 0.0125 * R); // Scale the sphere
    glRotatef(90, 1, 0, 0); // Rotate to correct orientation

    glBindTexture(GL_TEXTURE_2D, texture); // Bind the texture
    glBegin(GL_TRIANGLE_STRIP);
    for (int b = 0; b < VertexCount; b++) {
        glTexCoord2f(VERTEX[b].U, VERTEX[b].V);
        glVertex3f(VERTEX[b].X, VERTEX[b].Y, -VERTEX[b].Z);
    }
    for (int b = 0; b < VertexCount; b++) {
        glTexCoord2f(VERTEX[b].U, -VERTEX[b].V);
        glVertex3f(VERTEX[b].X, VERTEX[b].Y, VERTEX[b].Z);
    }
    glEnd();
}

Tutorial Code

Here is the full code for generating and rendering a textured sphere in OpenGL:

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

GLuint texture[1];
double angle = 0;

typedef struct {
    float X, Y, Z;
    double U, V;
} VERTICES;

const double PI = 3.1415926535897;
const int space = 10;
const int VertexCount = (90 / space) * (360 / space) * 4;
VERTICES VERTEX[VertexCount];

void CreateSphere(double R, double H, double K, double Z);
void DisplaySphere(double R, GLuint texture);

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0, 0, -10);
    glRotatef(angle, 0, 1, 0);
    DisplaySphere(5, texture[0]);
    glutSwapBuffers();
    angle++;
}

void init() {
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    texture[0] = LoadTextureRAW("texture.raw");
    CreateSphere(70, 0, 0, 0);
}

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutCreateWindow("OpenGL Sphere");
    init();
    glutDisplayFunc(display);
    glutIdleFunc(display);
    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
  • 34