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 customization, 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 visualization.

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 
#include 
#include 
#include 
#include 

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;
}

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

  • March 25, 2010
  • 34