Search code examples
c++openglgeometrydrawvbo

Incomplete sphere OpenGL


I want to draw a sphere using VBO for vertex, color and UV coordinates for texture. My problem is that the sphere is not 'closed', there is a hole in the origin. I know that this is because my code depends on (1/segments) distance between each vertex; I am working with segments = 40. I know that, if I rise that value, the hole will be lower, but program is slower. I don't know if there's a way to eliminate the hole without rise the variable.

Here's the code:

for(int i = 0; i <= segments; i++){

    double lat0 = pi * (-0.5 + (double)(i - 1) / segments);
    double z0 = sin(lat0);
    double zr0 = cos(lat0);
    // lat1 = [-pi/2..pi/2]
    double lat1 = pi * (-0.5 + (double)i / segments);
    double z1 = sin(lat1);
    double zr1 = cos(lat1);

    for (int j = 0; j <= segments; j++){    // Longitud
        // lng = [0..2*pi]
        double lng = 2 * pi * (double)(j - 1) / segments;
        double x = cos(lng);
        double y = sin(lng);
        //glNormal3f(x * zr0, y * zr0, z0); // Normals
        ballVerts.push_back(x * zr0); //X
        ballVerts.push_back(y * zr0); //Y
        ballVerts.push_back(z0);      //Z

        ballVerts.push_back(0.0f);
        ballVerts.push_back(0.0f);
        ballVerts.push_back(0.0f);
        ballVerts.push_back(1.0f); //R,G,B,A

        texX = abs(1 - (0.5f + atan2(z0, x * zr0) / (2.0 * pi)));
        texY = 0.5f - asin(y * zr0) / pi;
        ballVerts.push_back(texX);  // Texture coords
        ballVerts.push_back(texY);  // U, V


        //glNormal3f(x * zr1, y * zr1, z1); //Normals
        ballVerts.push_back(x * zr1); //X
        ballVerts.push_back(y * zr1); //Y
        ballVerts.push_back(z1);      //Z
        ballVerts.push_back(0.0f);
        ballVerts.push_back(0.0f);
        ballVerts.push_back(1.0f);
        ballVerts.push_back(1.0f); //R,G,B,A

        texX = abs(1 - (0.5f + atan2(z1, x * zr1) / (2.0 * pi)));
        texY = 0.5f - asin(y * zr1) / pi;
        ballVerts.push_back(texX);  // Texture coords
        ballVerts.push_back(texY);

    }
}
// Create VBO....

And this is the output I have:

enter image description here


Solution

  • I don't think that's a hole. You're drawing one segment too many, and causing it to draw additional triangles at the south pole, with the texture wrapped around:

    for(int i = 0; i <= segments; i++){
        double lat0 = pi * (-0.5 + (double)(i - 1) / segments);
    

    In the first loop iteration, with i = 0, the angle will be less than -0.5 * pi, resulting in the extra triangles shown in your picture.

    If you want to split the latitude range into segments pieces, you only need to run through the outer loop segments times. With the code above, with the loop from 0 up to and including segments, you're iterating segments + 1 times.

    The easiest way to fix this is to start the loop at 1:

    for(int i = 1; i <= segments; i++){
        double lat0 = pi * (-0.5 + (double)(i - 1) / segments);
    

    I would probably loop from 0 and make the end exclusive, and change the angle calculations. But that's really equivalent:

    for(int i = 0; i < segments; i++){
        double lat0 = pi * (-0.5 + (double) / segments);
        ...
        double lat1 = pi * (-0.5 + (double)(i + 1) / segments);