Maggie S.
Maggie S.

Reputation: 1136

Drawing a Circle with OpenGL

I'm trying to manipulate some code to draw a circle instead of the triangle that is already being printed by the tutorial. I'm not super familiar with C++ or OpenGL, which is why I'm just trying it out.

Any suggestions or corrections to my code would be greatly appreciated. I keep getting a breakpoint error in XCODE on this line:

glDrawArrays(GL_TRIANGLE_FAN, 0, numPoints); // draw the points and fill it in

and it says:

Thread 1: EXC_BAD_ACCESS(code=1, address=0x0)

Here is the original vector buffer for the triangle in the tutorial I'm following:

static const GLfloat g_vertex_buffer_data[] = { 
     -1.0f,  -1.0f, 0.0f,
     1.0f,  -1.0f, 0.0f,
     0.0f,  1.0f, 0.0f,
};

I'm pretty sure that my calculations are correct, but I don't know why it' not drawing a circle. Here is my manipulation:

// Make a circle
GLfloat x;
GLfloat y;
GLfloat z = 0.0f;
int theta = 0;
float radius = 50.0f;
int currentSize = 0;
int numPoints = 30;
GLfloat g_vertex_buffer_data[numPoints*3];

while (theta <= 360) {

    x = (GLfloat) radius * cosf(theta);
    y = (GLfloat) radius * sinf(theta);

    g_vertex_buffer_data[currentSize++] = x;
    g_vertex_buffer_data[currentSize++] = y;
    g_vertex_buffer_data[currentSize++] = z;

   /*
    cout << "Theta: " << theta << endl;

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

        cout << "g_vertex_buffer_data[" << g_vertex_buffer_data[i] << "]" << endl;
    }
    */

    theta = theta + (360/numPoints);
}

Here is the rest of the code in the .cpp file:

GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),g_vertex_buffer_data, GL_STATIC_DRAW);

do{

    // Clear the screen
    glClear( GL_COLOR_BUFFER_BIT );

    // Use our shader
    glUseProgram(programID);

    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(vertexPosition_modelspaceID);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
        vertexPosition_modelspaceID, // The attribute we want to configure
        numPoints,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );

    // Draw the circle!
    glDrawArrays(GL_TRIANGLE_FAN, 0, numPoints); // draw the points and fill it in

    glDisableVertexAttribArray(vertexPosition_modelspaceID);

    // Swap buffers
    glfwSwapBuffers(window);
    glfwPollEvents();

} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
       glfwWindowShouldClose(window) == 0 );


// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteProgram(programID);

// Close OpenGL window and terminate GLFW
glfwTerminate();

return 0;

Upvotes: 0

Views: 7209

Answers (1)

Reto Koradi
Reto Koradi

Reputation: 54602

There are a few problems in this code. The most severe one that probably causes the crash is here:

glVertexAttribPointer(
    vertexPosition_modelspaceID, // The attribute we want to configure
    numPoints,                  // size
    GL_FLOAT,           // type
    GL_FALSE,           // normalized?
    0,                  // stride
    (void*)0            // array buffer offset
);

The second argument to glVertexAttribPointer() is the number of components per vertex. Since you have 3 floats (x, y and z) per vertex, the correct value is 3. So the call should be:

glVertexAttribPointer(
    vertexPosition_modelspaceID, // The attribute we want to configure
    3,                  // size
    GL_FLOAT,           // type
    GL_FALSE,           // normalized?
    0,                  // stride
    (void*)0            // array buffer offset
);

There is also a 1-off error where the points are created:

while (theta <= 360) {

If you include 360 in the range, you will effectively repeat the first vertex, and write one more vertex than the allocated space. This should be:

while (theta < 360) {

Also, the arguments to cosf() and sinf() are in radians. So you will have to convert the angles from degrees to radians for these functions:

x = (GLfloat) radius * cosf(theta * M_PI / 180.0f);
y = (GLfloat) radius * sinf(theta * M_PI / 180.0f);

Upvotes: 2

Related Questions