1
\$\begingroup\$

I'm trying to create vertex and index buffer for a cylinder (in OpenGL, but it shouldn't matter). I think my vertex buffer is fine (I checked drawing with GL_POINTS). Here's the code that builds it:

int sides = 10, slices = 40;
float radius = 3.5 * 10.0;

numVertices = sides * slices;
Vertices = malloc(sizeof(Vertex) * numVertices);

int angleincs = 2*M_PI/sides;
int cs_angleincs = 2*M_PI/slices;
float zval;
float zstep = height / (float)sides;

float i;

for(int m=0; m<slices; m++)
{
    int index = (m*sides);
    for (int n=0; n<sides; n++)
    {
        Vertices[index + n].Position.x = cosf(i);
        Vertices[index + n].Position.y = sinf(i);
        Vertices[index + n].Position.z = zval;

        i += angleincs;
    }

    zval += zstep;
}

I'm stuck at the index buffer generation. Any help on how to build it? I tried to adapt some code from a torus generator, and I get something that apparently resembles a cylinder but it's a bit weird and has a few extra weird triangles.

numIndices = (2 * (sides+1) * slices + slices);
Indices = malloc(sizeof(GLushort) * numIndices);

int n=0;
for (int i=0;i<slices; i++) {
    for (int j=0; j<sides; j++) {
        Indices[n++] = i * sides + j;
        Indices[n++] = ((i+1)%slices) * sides + j;
    }

    Indices[n++] = i * sides;
    Indices[n++] = ((i+1)%slices) * sides;
    Indices[n++] = ((i+1)%slices) * sides;
}

Thanks in advance.

\$\endgroup\$
1
\$\begingroup\$

To texture a cylinder you typically use GL_TRIANGLE_FAN for the top and bottom and a GL_TRIANGLE_STRIP (just a normal array, without element arrays) for the around.

This is code to produce a normal array of vertices to be used with an array.

// draws a cylinder 'height' high on the y axis at x,y,z position
const float theta = 2. * M_PI / (float)sides;
    c = cos(theta),
    s = sin(theta);
// coordinates on top of the circle, on xz plane
float x2 = radius, z2 = 0;
// make the strip
glBegin(GL_TRIANGLE_STRIP);
for(int i=0; i<=sides; i++) {
    // texture coord
    const float tx = (float)i/sides;
    // normal
    const float nf = 1./math.sqrt(x2*x2+z2*z2),
        xn = x2*nf, zn = z2*nf;
    glNormal3f(xn,0,zn);
    glTexCoord2f(tx,0);
    glVertex3f(x+x2,y,z+z2)
    glNormal3f(xn,0,zn);
    glTexCoord2f(tx,1);
    glVertex3f(x+x2,y+height,z+z2);
    // next position
    const float x3 = x2;
    x2 = c * x2 - s * z2;
    z2 = s * x3 + c * z2;
}
glEnd();

It is straightforward to adapt this to have store those vertices in a VBO for glDrawArrays to use.

without GL_CULL_FACE

\$\endgroup\$
5
  • \$\begingroup\$ Hey, thanks. So you suggest using a triangle fan rather than a strip, and no indices? As I said I'm on the iPhone. Also, what about texture coordinates? \$\endgroup\$
    – pt2ph8
    Sep 13 '11 at 13:24
  • \$\begingroup\$ absolutely, don't bother with indices! They are just more code, bigger VBOs and slower to boot! I added computation of a texutre and the normals. \$\endgroup\$
    – Will
    Sep 13 '11 at 14:30
  • \$\begingroup\$ It works, but I need to build the cylinder using many 'slices'. I tried to adapt your code but whenever I set slices to more than 1, the geometry starts looking weird. Could you please check my code? It's basically yours + a 'delta slice' variable which gets added to y for each slice loop. Code: pastebin.com/VfHbmT14 Screen: i.imgur.com/Lomvm.png \$\endgroup\$
    – pt2ph8
    Sep 13 '11 at 21:25
  • \$\begingroup\$ @pt2ph8 what's a slice and a side? And why a slice? \$\endgroup\$
    – Will
    Sep 14 '11 at 6:49
  • \$\begingroup\$ I think I just solved it myself. Basically I just wanted to divide the cylinder into smaller cylinders ("slices") to fill the whole height. \$\endgroup\$
    – pt2ph8
    Sep 14 '11 at 12:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.