3

I have been trying to create a circle in OpenGL but I cannot use triangle fans because I have read they are not available in directx anymore and I will also be making directx calls.

I could not really understand how triangle strips work. All my implementations had holes or weird quirks, can anybody help me out here, how can I implement it in the best possible way?

Also is there really any performance difference between triangle strips and seperate triangles, for lets say 10 circles with 1000 triangles each. Will it make a lot of difference?

4

3 回答 3

6

One way to specify a circle with a triangle strip is as follows:

for each step
    add next position on circle
    add circle center

This will include the circle's center position. Another way without including the center is this:

add left most vertex
for each phi in (-PI/2, Pi/2) //ommit the first and last one
    x = r * sin(phi)
    y = r * cos(phi)
    add (x, y)
    add (x, -y)
add right most vertex

You may need to adjust the loops depending on your backface culling settings

The topologies require different numbers of vertices. For a triangle list 10 circles á 1000 triangles need 30,000 vertices. With a triangle strip you need 1002 vertices per circle, so overall 10,020 vertices. This is almost three times smaller, which should be a bit faster when transferring to the CPU. If this is reflected in the FPS depends on several things.

于 2013-03-08T14:59:52.237 回答
3

Here is code using VAO/VBO, and the minimum number of points. Unlike the other answers posted so far, it only needs one cos() and one sin() call.

Setup:

// Number of points used for half circle.
const unsigned HALF_PREC = 10;

const float angInc = M_PI / static_cast<float>(HALF_PREC);
const float cosInc = cos(angInc);
const float sinInc = sin(angInc);

GLfloat* coordA = new GLfloat[2 * HALF_PREC * 2];
unsigned coordIdx = 0;

coordA[coordIdx++] = 1.0f;
coordA[coordIdx++] = 0.0f;

float xc = 1.0f;
float yc = 0.0f;
for (unsigned iAng = 1; iAng < HALF_PREC; ++iAng) {
    float xcNew = cosInc * xc - sinInc * yc;
    yc = sinInc * xc + cosInc * yc;
    xc = xcNew;

    coordA[coordIdx++] = xc;
    coordA[coordIdx++] = yc;

    coordA[coordIdx++] = xc;
    coordA[coordIdx++] = -yc;
}

coordA[coordIdx++] = -1.0f;
coordA[coordIdx++] = 0.0f;

GLuint vaoId = 0;
glGenVertexArrays(1, &vaoId);
glBindVertexArray(vaoId);

GLuint vboId = 0;
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, 2 * HALF_PREC * 2 * sizeof(GLfloat),
             coordA, GL_STATIC_DRAW);

delete[] coordA;

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);

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

Draw:

glBindVertexArray(vaoId);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 2 * HALF_PREC);
glBindVertexArray(0);
于 2014-10-26T07:16:23.923 回答
2
for each phi in (-PI, Pi) //ommit the first and last one
    x1 = r * sin(phi)
    y1 = r * cos(phi)

    x2 = r * sin(phi + Pi)
    y2 = r * cos(phi + Pi)

    add (x1, y1)
    add (x2, y2)

Instead zigging up and down on one side of the circle as above pseudo code shown, this one will zig zag across the center of the circle. This will have much fuller circle.

于 2014-10-26T04:33:27.903 回答