Thread: OpenGL: Draw cylinder yourself

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    1

    Question 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!

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    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).

  3. #3
    Registered User
    Join Date
    Mar 2010
    Posts
    68
    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);
    }
    Last edited by smasherprog; 01-10-2011 at 08:24 PM.

  4. #4
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,739
    Damn, smasherprog!! Are you building a game engine or something? Pretty good code!
    Devoted my life to programming...

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    68

    yes, i am

    Funny you should say, yes I am building a game engine :P

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to make opengl draw in lighter colors ?
    By jabka in forum Game Programming
    Replies: 2
    Last Post: 12-17-2007, 06:12 AM
  2. Need some help drawing a cylinder in openGL
    By InvariantLoop in forum Game Programming
    Replies: 4
    Last Post: 10-25-2005, 02:19 AM
  3. OpenGL Window
    By Morgul in forum Game Programming
    Replies: 1
    Last Post: 05-15-2005, 12:34 PM
  4. OpenGL .dll vs video card dll
    By Silvercord in forum Game Programming
    Replies: 14
    Last Post: 02-12-2003, 07:57 PM
  5. opengl code not working
    By Unregistered in forum Windows Programming
    Replies: 4
    Last Post: 02-14-2002, 10:01 PM

Tags for this Thread