Search code examples
openglgeometrytexturesjogl

What is the correct way to map a texture on a sphere?


I'm having problems with the correct mapping of a sphere. I used a world-map to show where it goes wrong. North America appears on the front from top to bottom, while South America is on the other side upside down and continents like Asia are not even on the map.

Screenshot
(source: troll.ws)

The code below is the sphere-object

class Shape {
    
    public void drawSphere(double radius, int slices, int stacks) {
        gl.glEnable(GL_TEXTURE_2D);
        head.bind(gl); //Method that binds the world-map (for testing) texture.
        gl.glBegin(GL_QUADS);
        double stack = (2 * PI) / stacks;
        double slice = (2 * PI) / slices;
        for (double theta = 0; theta < 2 * PI; theta += stack) {
            for (double phi = 0; phi < 2 * PI; phi += slice) {
                Vector p1 = getPoints(phi, theta, radius);
                Vector p2 = getPoints(phi + slice, theta, radius);
                Vector p3 = getPoints(phi + slice, theta + stack, radius);
                Vector p4 = getPoints(phi, theta + stack, radius);
                double s0 = theta / (2 * PI);
                double s1 = (theta + stack) / (2 * PI);
                double t0 = phi / (2 * PI);
                double t1 = (phi + slice) / (2 * PI);
                                                      
                vectorToNormal(norm(p1));
                gl.glTexCoord2d(s0, t0);
                vectorToVertex(p1);
                
                vectorToNormal(norm(p2));
                gl.glTexCoord2d(s0, t1);
                vectorToVertex(p2);
                
                vectorToNormal(norm(p3));
                gl.glTexCoord2d(s1, t1 );
                vectorToVertex(p3);
                
                vectorToNormal(norm(p4));
                gl.glTexCoord2d(s1, t0);
                vectorToVertex(p4);
            }
        }
        gl.glEnd();
        gl.glDisable(GL_TEXTURE_2D);
    }
    
    Vector getPoints(double phi, double theta, double radius) {
        double x = radius * cos(theta) * sin(phi);
        double y = radius * sin(theta) * sin(phi);
        double z = radius * cos(phi);
        return new Vector(x, y, z);
    }

How can I fix it? I tried swapping some coordinates and other things, but that made it even messier for me.

Also, there seem to be some artifacts when on the spere when I bind the texture to it. Is that fixable?


Solution

  • Both your loops are going from 0 to 2*PI. One of them should only be a half circle. You've doubled up the sphere, resulting in the dodgy mapping and the strange artefacts.