# OpenGL: Draw cylinder yourself

• 01-10-2011
iMPR3SSiON
OpenGL: Draw cylinder yourself
Hello, I am not struggling with OpenGL and have this particular problem:

I'd like to draw a cylinder myself. Not just use gluCylinder() and everything. It is interesting for me to know, how to do it.

I've started with octagon, drew two of them, put them on top of each other in some distance. Then I drew the cover to make it cylindrical.

!And then the cage came down!

It started to do weird things, it drew covering and one octagon and that was it. No cylinder what so ever! I spend a lot of time figuring out how to fix it, but I didn't succeed :(

Here is the code, I'd like to ask some kind people to find this particular mistake or so.
I've commented it here and there to make it easier.

Code:

```#include "cstdio" #include "GL/glut.h" #include "math.h" void drw_polygon(int n = 3, int arg = 0, float mult = 1, float v = 1.0) {     /*         Function drw_polygon:         Arguments:             n - number of sides             arg - starting angle (not so important at all)             mult - multiplying sides to incrase their length             v - cylinder height     */     // DumbProof Double Check :)     if (arg < 0)         arg = 0;     // Cylinder Bottom     glBegin(GL_POLYGON);         glColor4f(1.0, 0.0, 0.0, 1.0);         for(int i = arg; i <= (360 + arg); i += (360 / n)) {             float a = i * M_PI / 180; // degrees to radians             glVertex3f(mult * cos(a), mult * sin(a), 0.0);         }         glEnd();     // Cylinder Top         glBegin(GL_POLYGON);         glColor4f(0.0, 0.0, 1.0, 1.0);         for(int i = arg; i <= (360 + arg); i += (360 / n)) {             float a = i * M_PI / 180; // degrees to radians             glVertex3f(mult * cos(a), mult * sin(a), v);         }         glEnd();     // Cylinder "Cover"         glBegin(GL_QUAD_STRIP);         glColor4f(1.0, 1.0, 0.0, 1.0);         for(int i = arg; i < 480; i += (360 / n)) {             float a = i * M_PI / 180; // degrees to radians             glVertex3f(mult * cos(a), mult * sin(a), 0.0);             glVertex3f(mult * cos(a), mult * sin(a), v);         }         glEnd(); } void display() {         glClear(GL_COLOR_BUFFER_BIT);     glRotatef(0.05, 1.0, 1.0, 0.0);     drw_polygon(3, 0, 2, 4);         glutSwapBuffers(); } void timer(int = 0) {         display();         glutTimerFunc(1, timer, 0); } int main(int argc, char **argv) {         glutInit(&argc, argv);         glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);         glutInitWindowSize(500, 500);         glutInitWindowPosition(200, 200);         glutCreateWindow("Cylinder");         glClearColor(0.0, 0.0, 0.0, 1.0);         glMatrixMode(GL_PROJECTION);         glLoadIdentity();         glOrtho(-5, 5, -5, 5, -5, 5);         glutDisplayFunc(display);         timer();         glutMainLoop(); }```
Thanks for any help!
• 01-10-2011
tabstop
So you appear to be drawing this thing edge-on; i.e. looking straight down the top (or straight up the bottom, or whatever). So you should see a triangle and that's about it since the rest of the prism is behind the triangle. Maybe you could draw it off-center (i.e. add 2 to all the x's or something to move it over) and then you might see the whole prism).
• 01-10-2011
smasherprog
here is my code. This function APPENDS a cylinder onto the data passed to the function. Generates normals, correct texture coords as well. The caller has to pass a 2 or 4 for the index stride as well

I use alot of my own function calls, like sin32 or cos32, and similarly for the math functions, but you should be able to swap them.

Code:

``` class cPNTVert{ public:         vec3 pos, norm;         vec2 tex; }; inline float DegToRad(const float& deg){ return deg*(Pi/180.0f); } //vector<cPNTVert>& v can contain vertices and in is the index buffer. They can already have data in them and you can use this function to append a cylinder onto the data already there void GenCylinder(size_t lengthsegs, size_t heightsegs, vector<cPNTVert>& v, vector<uint16_t>& in, size_t indexstride){         heightsegs+=1;// we need an extra one here!         size_t startvertex = v.size();// if v is empty, the size is 0, so we are starting on an empty buffer, but if there is data, this will append it correctly         size_t totalverts = lengthsegs*heightsegs;         v.resize(startvertex + totalverts);         vector<vec3> verts(totalverts), norms(totalverts);         vector<vec2> texs(totalverts);         float heightstride = 1.0f/static_cast<float>(lengthsegs);         float height = -heightstride;         float deg = 0;         for(size_t i(0); i< lengthsegs; i++){                 height+=heightstride;                 for(size_t j(0); j < heightsegs; j++){                         verts[i*heightsegs + j] = vec3(cos32(DegToRad(deg)), height, sin32(DegToRad(deg) ) );                         texs[i*heightsegs + j] = vec2(static_cast<float>(j)/(static_cast<float>(heightsegs)-1.0f), static_cast<float>(i+1));                         deg += 360/(static_cast<float>(heightsegs-1));                 }                 deg = 0.0f;         }         size_t nind = (6*(lengthsegs-1)*(heightsegs));         if(indexstride ==2 ){// two byte index stride                 size_t startindex = in.size();                 in.resize(nind + startindex);                 size_t off(0);                 for(size_t i(0); i< lengthsegs-1; i++){                         for(size_t j(0); j< heightsegs; j++){                                 in[off    + startindex] = i*heightsegs + j;                                 in[off + 1 + startindex] = (i+1)*heightsegs + j;                                 in[off + 2 + startindex] = i*heightsegs + j + 1;                                 in[off + 3 + startindex] = i*heightsegs + j + 1;                                 in[off + 4 + startindex] = (i+1)*heightsegs + j;                                 in[off + 5 + startindex] = (i+1)*heightsegs + j + 1;                                 off+=6;                         }                 }                 ComputeNormals(&verts[0], totalverts, &in[startindex], nind, &norms[0]);                 for(size_t i(0); i< (lengthsegs-1)*heightsegs*6; i++) in[i +startindex] += static_cast<uint16_t>(startvertex);// remap the indices         } else {// 4 byte index stride..                 size_t startindex = in.size();// beginning of our indices                 in.resize((nind*2) + startindex);// allocate twice as many                 uint32_t* indices = reinterpret_cast<uint32_t*>(&in[startindex]);                 size_t off(0);                 for(size_t i(0); i< lengthsegs-1; i++){                         for(size_t j(0); j< heightsegs; j++){                                 indices[off    ] = i*heightsegs + j;                                 indices[off + 1] = (i+1)*heightsegs + j;                                 indices[off + 2] = i*heightsegs + j + 1;                                 indices[off + 3] = i*heightsegs + j + 1;                                 indices[off + 4] = (i+1)*heightsegs + j;                                 indices[off + 5] = (i+1)*heightsegs + j + 1;                                 off+=6;                         }                 }                 ComputeNormals(&verts[0], totalverts, indices, nind, &norms[0]);                 for(size_t i(0); i< (lengthsegs-1)*heightsegs*6; i++) indices[i +startindex] += startvertex;// remap the indices         }         for(size_t i(0); i<totalverts; i++){                 v[i + startvertex].pos = verts[i];                 v[i + startvertex].tex = texs[i];                 v[i + startvertex].norm = norms[i];         } } template<class T>void ComputeNormals(vec3* Vertices, size_t numverts, T* indices, size_t numindices, vec3* normals){         size_t i = 0;         memset(normals, 0, sizeof(vec3)* numverts);         do{                 vec3 v0(Vertices[indices[i    ]]);                 vec3 v1(Vertices[indices[i + 1]]);                 vec3 v2(Vertices[indices[i + 2]]);                 vec3 normal(Cross(v1 - v0, v2 - v0));                 normal.normalize();                 normals[indices[i    ]] += normal;                 normals[indices[i + 1]] += normal;                 normals[indices[i + 2]] += normal;                 i += 3;         } while(i < numindices);         i=0;         do{ normals[i].normalize(); } while(++i < numverts); }```
• 01-11-2011
GReaper
Damn, smasherprog!! Are you building a game engine or something? Pretty good code!
• 01-11-2011
smasherprog
yes, i am
Funny you should say, yes I am building a game engine :P
• 01-11-2011
VirtualAce
A cylinder is two triangle fans connected by a triangle strip. I see no benefit in making your own since you would never do this in any type of game or renderer. The renderer would just load a cylinder model and render it just as any other mesh.