4

So I have created all of the correct sphere vertices using this algorithm:

GLint total = 100;
GLfloat radius = 200;
GLfloat sphereVertices[30000];
for (int i = 0; i < total; i++)
{
    float lon = map(i, 0, total, -M_PI, M_PI);
    for (int j = 0; j < total; j++)
    {
        float lat = map(j, 0, total, -M_PI/2, M_PI/2);

        sphereVertices[(i * 300) + (j * 3)] = radius * sin(lon) * cos(lat);
        sphereVertices[(i * 300) + (j * 3) + 1] = radius * sin(lon) * sin(lat);
        sphereVertices[(i * 300) + (j * 3) + 2] = radius * cos(lon);
    }

}

But when I draw it using either GL_TRIANGLES and GL_TRIANGLE_STRIP, I'm produced with this result: enter image description here

As you can see the only triangles which are being rendered are slicing through the center of the sphere. Is my math wrong? Or am I not plotting my data into my array the correct way for my glVertexAttribPointer function to read the data correctly?

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);

EDIT 1:

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glDrawArrays(GL_TRIANGLES, 0, 10000);
Sharpie
  • 113
  • 8
  • You are showing not enough and probably the wrong part of your code. We only see the calculation of the coordinates of the vertices. They obviously are correct, since they form a sphere. For rendering the sphere you need to use those vertices in groups. Each vertice gets used more often than once, one time for each polygon (probably triangle) it is part of. Also the order of being "mentioned" is very important. Possibly many more polygons are actually rendered, but facing the wrong direction. Make a [mcve] and then try this https://ericlippert.com/2014/03/21/find-a-simpler-problem/ – Yunnosch Mar 03 '18 at 04:14
  • I added the draw call to my question and I included how the data is parsed into the glVertexAttribPointer. My question was, "Is my math wrong? Or am I not plotting my data into my array the correct way for my glVertexAttribPointer function to read the data correctly?" – Sharpie Mar 03 '18 at 04:21
  • Find an example using the same APIs and compare it to your code. Check the order of vertices and the number of times each occurs. Consider simplifying to other geometries and then extending towards a sphere with many vertices. – Yunnosch Mar 03 '18 at 04:35

1 Answers1

6

You cant't draw the inices directly by glDrawArrays. You have to bring them in a proper order. Create a triangle index list and use glDrawElements

See also How to map texture to sphere that rendered by parametric equation using points primitive

Further note, that your loop should run from i = 0 to i <= total, because you want to create vertex coordinates on both poles of the sphere.

GLint layers             = 100;
GLint circumferenceTiles = 100;
std::vector<GLfloat> sphereVertices;
va.reserve( (layers+1)*(circumferenceTiles+1)*3 );  // 3 floats: x, y, z 
for ( int i = 0; i <= layers; ++ i )
{
    GLfloat lon     = map(i, 0, layers, -M_PI, M_PI);
    GLfloat lon_sin = std::sin( lon );
    GLfloat lon_cos = std::cos( lon );
    for ( int j = 0; j <= circumferenceTiles; j ++ )
    {
        GLfloat lat     = map(j, 0, circumferenceTiles, -M_PI/2, M_PI/2);
        GLfloat lat_sin = std::sin( lat);
        GLfloat lat_cos = std::cos( lat);

        va.push_back( lon_cos * lat_cos ); // x
        va.push_back( lon_cos * lat_sin ); // y
        va.push_back( lon_sin );           // z
    }
}

You can create triangles by stacking up discs:

enter image description here

// create the face indices 
std::vector<GLuint> ia;
ia.reserve( layers*circumferenceTiles*6 );
for ( GLuint il = 0; il < layers; ++ il )
{
    for ( GLuint ic = 0; ic < circumferenceTiles; ic ++ )
    {
      GLuint i0 = il * (circumferenceTiles+1) + ic;
      GLuint i1 = i0 + 1;
      GLuint i3 = i0 + circumferenceTiles+1;
      GLuint i2 = i3 + 1;

      int faces[]{ i0, i1, i2, i0, i2, i3 };
      ia.insert(ia.end(), faces+(il==0?3:0), faces+(il==layers-1?3:6));
    }
}

Specify the vertex array object:

GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sphereVertices.size()*sizeof(GLfloat), sphereVertices.data(), 
GL_STATIC_DRAW );

GLuint ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, ia.size()*sizeof(GLuint), ia.data(), GL_STATIC_DRAW );

GLuint v_attr_inx = 0;
glVertexAttribPointer( v_attr_inx , 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( v_attr_inx );

glBindVertexArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );

Draw the sphere:

glBindVertexArray( vao );
glDrawElements( GL_TRIANGLES, (GLsizei)ia.size(), GL_UNSIGNED_INT, 0 );
glBindVertexArray( 0 );
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • thank you for the help with that, makes alot more sense now because my calculations of all the vertices would've been all over the place, and there would be no order for the triangles to be created in, leading to the bizarre result I had. Thanks for helping me see what I should've been doing. – Sharpie Mar 13 '18 at 11:49