Brothre23
Brothre23

Reputation: 39

Drawing a sphere with OpenGL

Can someone please tell me which part of the code I'm messing up?

In glDrawElements, I got like only 1/3 of the sphere with "indices.size() / 3" , which was how most tutorial was conducted, but when I tried indices.size(), I got segmentation fault and nothing showed up.

vector<GLfloat> vertices, normals, texCoords;
vector<GLushort> indices;

void setupSphere(double r, int slice, int stack)
{
    vertices.resize(slice * stack * 3);
    normals.resize(slice * stack * 3);
    texCoords.resize(slice * stack * 2);

    float x, y, z, xz;
    float nx, ny, nz, lengthInv = 1.0f / r;
    float s, t;

    float sliceAngle, stackAngle;

    vector<GLfloat>::iterator itV = vertices.begin();
    vector<GLfloat>::iterator itN = normals.begin();
    vector<GLfloat>::iterator itT = texCoords.begin();

    for (int i = 0; i < stack; i++)
    {
        stackAngle = M_PI_2 - M_PI * i / stack;
        xz = r * cosf(stackAngle);
        y = r * sinf(stackAngle);

        for (int j = 0; j < slice; j++)
        {
            sliceAngle = 2 * M_PI * j / slice;

            x = xz * sinf(sliceAngle);
            z = xz * cosf(sliceAngle);
            *itV++ = x;
            *itV++ = y;
            *itV++ = z;

            nx = x * lengthInv;
            ny = y * lengthInv;
            nz = z * lengthInv;
            *itN++ = nx;
            *itN++ = ny;
            *itN++ = nz;

            s = (float)j / slice;
            t = (float)i / stack;
            *itT++ = s;
            *itT++ = t;
        }
    }

    int first, second;
    for (int i = 0; i < stack; i++)
    {
        for (int j = 0; j < slice; j++)
        {
            first = i * slice + j;
            second = first + slice + 1;

            indices.push_back(first);
            indices.push_back(second);
            indices.push_back(first + 1);

            indices.push_back(first + 1);
            indices.push_back(second);
            indices.push_back(second + 1);
        }
    }
}

void drawSphere()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
    glNormalPointer(GL_FLOAT, 0, &normals[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, &texCoords[0]);

    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, &indices[0]);
}

Upvotes: 1

Views: 1074

Answers (2)

Rabbid76
Rabbid76

Reputation: 210889

You generate N stacks and M slices. Hence you can just create (N-1)x(M-1) quads.
The indices of the quads are (first, first+slice, first+1, first+slice+1), where first is the first index of the quad:

for (int i = 0; i < stack-1; i++)
{
    for (int j = 0; j < slice-1; j++)
    {
        int first = i*slice + j;
        unsigned short qi[]{first, first+slice, first+1, first+slice+1};

        indices.insert(indices.end(), {qi[0], qi[2], qi[3], qi[0], qi[3], qi[1]});
    }
}

See the answer to the questions Sphere Calculations and How to map texture to sphere that rendered by parametric equation using points primitive.

Upvotes: 1

lvella
lvella

Reputation: 13413

The correct is indeed indices.size() / 3, because you must pass the number of triangles, not the number of indices.

The correct is indeed indices.size(), because you must pass the number of elements in the array you are passing. I don't know why the tutorials you saw used / 3 variation.

As to the problem of the missing sphere section, my best guess with the provided information is that you have more than 65535 vertices, so the indices wraps around that value, because you are using GL_UNSIGNED_SHORT.

Try changing from vector<GLushort> indices; to vector<GLuint> indices; and using GL_UNSIGNED_INT in glDrawElements().

Alternatively, lower the values of slice and stack so that slice * stack * 3 <= 65535.

Upvotes: 1

Related Questions