1

Trying to implement a sphere example code I found here on stackoverflow I have been running into problems. Note that I am not using the draw code, I am using the void SolidSphere function from this example to create my vertex data.

This is my code with some minor changes to the example that I refered to:

std::vector<GLfloat> vertices;
std::vector<GLfloat> normals;
std::vector<GLfloat> texcoords;
std::vector<GLushort> indices;

    Sphere(shared_ptr<GL::Shader> _shader, shared_ptr<Material> _material, float radius, unsigned int rings, unsigned int sectors)
{
    this->attachShader(_shader);
    this->attachMaterial(_material);

    /** Implementation from:
    https://stackoverflow.com/questions/5988686/how-do-i-create-a-3d-sphere-in-opengl-using-visual-c?lq=1
    **/

    float const R = 1./(float)(rings-1);
    float const S = 1./(float)(sectors-1);
    int r, s;

    vertices.resize(rings * sectors * 3);
    //normals.resize(rings * sectors * 3);
    texcoords.resize(rings * sectors * 2);
    std::vector<GLfloat>::iterator v = vertices.begin();
    //std::vector<GLfloat>::iterator n = sphere_normals.begin();
    std::vector<GLfloat>::iterator t = texcoords.begin();
    for(r = 0; r < rings; r++) {
        for(s = 0; s < sectors; s++) {
            float const y = sin( -M_PI/2 + M_PI * r * R );
            float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );
            float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );

            *t++ = s*S;
            *t++ = r*R;

            *v++ = x * radius;
            *v++ = y * radius;
            *v++ = z * radius;

            //*n++ = x;
            //*n++ = y;
            //*n++ = z;
        }
    }



    indices.resize(rings * sectors * 4);
    std::vector<GLushort>::iterator i = indices.begin();
    for(r = 0; r < rings; r++) {
        for(s = 0; s < sectors; s++) {
            *i++ = r * sectors + s;
            *i++ = r * sectors + (s+1);
            *i++ = (r+1) * sectors + (s+1);
            *i++ = (r+1) * sectors + s;
        }
    }


           /************* THIS IS THE ADDED PART ********/
    for (unsigned int i = 0; i < vertices.size(); i += 3) {
        vertexCoords.push_back(glm::vec4(vertices[i], vertices[i+1], vertices[i+2], 1));
    }

    for (unsigned int i = 0; i < texcoords.size(); i += 2) {
        textureCoords.push_back(glm::vec2(texcoords[i], texcoords[i+1]));
    }
    indexElements = indices;

    cout << "Vertex vector size: " << vertexCoords.size() << endl;
    cout << "Texture vector size: " << textureCoords.size() << endl;
    cout << "Element index vector size: " << indexElements.size() << endl;
}

The only big change here is using M_PI / 2 instead of M_PI_2 and two loops that pushes the value into the format my code uses which is:

vector <glm::vec4> vertexCoords;
vector <glm::vec2> textureCoords;
vector <GLushort> indexElements;

Here is a picture of what I am rendering:

enter image description here

so I am seeing this last line on the top of the sphere..

Is it anything obvious I am doing wrong in this code that could cause this?

Community
  • 1
  • 1
toeplitz
  • 777
  • 1
  • 8
  • 27
  • 3
    that approach is deprecated, you should step into OpenGL 3.x and newer. – user1824407 Dec 29 '12 at 10:52
  • how is this related to ogl version? I am just preparing vertex data which I use to fill my buffers. – toeplitz Dec 29 '12 at 10:57
  • if you are drawing something this means that you are rendering something, and since the question is about OpenGL i think that you are using OpenGL, but in a deprecated way. The word "deprecated" in OpenGL means that "you can find a vga brand that can or cannot implent this function, but the Khronos group highly discourage the adoption of this or that functions in your code and driver", in short deprecated functions are not granted to fully/partially work . You program is a result of this deprecated approach. – user1824407 Dec 29 '12 at 11:01
  • added to my post.. I am not using the draw function from that example, just using the `void SolidSphere` code to create the vertex data which I then upload to the gpu. – toeplitz Dec 29 '12 at 11:02
  • Then remove `mode = GL_QUADS` at the end of the function to get rid of the rest of the evidence;) – kerim Dec 29 '12 at 11:50
  • Can you narrow your drawcall to the last line? Try removing the calls, so only the last line is left. Most probably it's some sort of `LINE_STRIP`. – Bartek Banachewicz Dec 29 '12 at 12:03
  • @user1824407: depreceated in the context of OpenGL means, that the functionality in question is about to be phased out in upcomming versions of OpenGL. But all currently available GPUs support old OpenGL versions just fine. – datenwolf Dec 29 '12 at 15:11
  • I updated the source code in the original answer to address any remaining issues; it went through a number of stylistic revisions and I not always tested them (writing it on smartphones or such). – datenwolf Dec 29 '12 at 15:40

3 Answers3

2

In this loop:

for(r = 0; r < rings; r++) {
    for(s = 0; s < sectors; s++) {
        *i++ = r * sectors + s;
        *i++ = r * sectors + (s+1);
        *i++ = (r+1) * sectors + (s+1);
        *i++ = (r+1) * sectors + s;
    }
}

you are accessing r+1 and s+1 which when r = rings - 1 and s = sectors - 1 (i.e. the last iteration of your loops) will be one higher than the data you have available.

This will be pointing to an uninitialised area of memory. This could contain anything, but in this case it appears to contain zeros which would explain the line going off to the origin.

As you are drawing the "next" quad you simply need to stop these loops one iteration earlier:

for(r = 0; r < rings-1; r++) {
    for(s = 0; s < sectors-1; s++) {
ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • Thanks, so by the looks of it the answer in [this post](http://stackoverflow.com/questions/5988686/how-do-i-create-a-3d-sphere-in-opengl-using-visual-c?lq=1) has this error.. – toeplitz Dec 29 '12 at 12:32
  • @toeplitz - good find. It's an old question and answer, but a comment might be in order. – ChrisF Dec 29 '12 at 12:33
1

You have only rings*sectors vertices but your indices go up to (rings-1+1)*sectors+(sectors-1+1)=rings*sectors+sectors. Which is exactly sectors number of vertices too much.

kerim
  • 2,412
  • 18
  • 16
1

The problem is the output indices of bounds. Try to fix this part of the code so

indices.resize(rings * sectors * 4);
std::vector<GLushort>::iterator i = indices.begin();
for(r = 0; r < rings-1; r++) {
    for(s = 0; s < sectors-1; s++) {
        *i++ = r * sectors + s;
        *i++ = r * sectors + (s+1);
        *i++ = (r+1) * sectors + (s+1);
        *i++ = (r+1) * sectors + s;
    }
}
yvaschuk
  • 59
  • 2