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 Answer 1

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\$
    – ySgPjx
    Sep 13, 2011 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, 2011 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\$
    – ySgPjx
    Sep 13, 2011 at 21:25
  • \$\begingroup\$ @pt2ph8 what's a slice and a side? And why a slice? \$\endgroup\$
    – Will
    Sep 14, 2011 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\$
    – ySgPjx
    Sep 14, 2011 at 12:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .