Here\'s the cylinder I have created:
void drawCylinder(float r, float g, float b) {
setMaterialColors(r, g, b);
glColor4f(r, g, b, 1.0);
/* top t
It looks like you have a functional solution. But there's a few more things that I think are worth improving compared to the original code, so I still want to provide an alternative. It addresses:
sin
/cos
calls, as well as divisions, which are all fairly expensive. The code below uses one sin
, one cos
, and a couple of divisions that can be evaluated at compile time. The rest is all additions and multiplications, which are much faster operations.float
, double
and int
types. float
is fine for coordinates, there is no need to use slower double precision, with also expensive type casts back to float
.Code (untested, but hopefully close enough to convey the proposed approach):
// Number of segments a circle is divided into.
const unsigned DIV_COUNT = 32;
// Calculate angle increment from point to point, and its cos/sin.
float angInc = 2.0f * M_PI / static_cast(DIV_COUNT);
float cosInc = cos(angInc);
float sinInc = sin(angInc);
// Draw top cap.
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.5f, 0.5f);
glVertex3f(0.0f, height, 0.0f);
glTexCoord2f(1.0f, 0.5f);
glVertex3f(radius, height, 0.0f);
float xc = 1.0f;
float yc = 0.0f;
for (unsigned iDiv = 1; iDiv < DIV_COUNT; ++iDiv) {
float xcNew = cosInc * xc - sinInc * yc;
yc = sinInc * xc + cosInc * yc;
xc = xcNew;
glTexCoord2f(0.5f + 0.5f * xc, 0.5f + 0.5f * yc);
glVertex3f(radius * xc, height, -radius * yc);
}
glTexCoord2f(1.0f, 0.5f);
glVertex3f(radius, height, 0.0f);
glEnd();
// Draw bottom cap.
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.5f, 0.5f);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.5f);
glVertex3f(radius, 0.0f, 0.0f);
xc = 1.0f;
yc = 0.0f;
for (unsigned iDiv = 1; iDiv < DIV_COUNT; ++iDiv) {
float xcNew = cosInc * xc - sinInc * yc;
yc = sinInc * xc + cosInc * yc;
xc = xcNew;
glTexCoord2f(0.5f + 0.5f * xc, 0.5f + 0.5f * yc);
glVertex3f(radius * xc, 0.0f, radius * yc);
}
glTexCoord2f(1.0f, 0.5f);
glVertex3f(radius, 0.0f, 0.0f);
glEnd();
float texInc = 1.0f / static_cast(DIV_COUNT);
// Draw cylinder.
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(radius, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(radius, height, 0.0f);
xc = 1.0f;
yc = 0.0f;
float texCoord = 0.0f;
for (unsigned iDiv = 1; iDiv < DIV_COUNT; ++iDiv) {
float xcNew = cosInc * xc - sinInc * yc;
yc = sinInc * xc + cosInc * yc;
xc = xcNew;
texCoord += texInc;
glTexCoord2f(texCoord, 0.0f);
glVertex3f(radius * xc, 0.0f, radius * yc);
glTexCoord2f(texCoord, 1.0f);
glVertex3f(radius * xc, height, radius * yc);
}
glTexCoord2f(0.0f, 0.0f);
glVertex3f(radius, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(radius, height, 0.0f);
glEnd();
If you're interested in moving to modern OpenGL, my answer to this question shows how to draw a circle using VBOs: How to draw a circle using VBO in ES2.0.