glutSolidTeapot weirdness

Just thought I’d post something weird I ran into that I’ve never heard of before. I was messing around with the cubic environment mapping extensions a bit, and instead of creating my own model for the testing, I just used glutSolidTeapot.

Everything worked fine. I had a rotating teapot, with my simple cubic environment map. Next I decided to rotate the texture around instead of the teapot.

I switched the matrix mode to GL_TEXTURE, did my rotate, drew my teapot, then switched back to GL_MODELVIEW. You can imagine my surprise when, instead of rotating my texture, my teapot flipped onto it’s side!

I was playing with this on my new work computer, which has an embedded Intel chip. My first thought was that the OpenGL implementation for that was buggy in the area of the texture matrix. I messed around with it a bit more, though.

I finally narrowed down the problem, though. And it appears that it happens on my GeForce2 as well. What I found suggests that it’s a weirdness with the glutSolidTeapot call itself.

What I found is that if the GL_TEXTURE matrix is the current matrix when glutSolidTeapot is called, it gets drawn on its side. My guess is that this function uses matrix manipulations for drawing, and simply assumes that the current matrix is the GL_MODELVIEW.

In any case, it’s not a huge problem. I was simply using the teapot for a test model, in place of some other code I hadn’t completed yet. It was just something I found a bit interesting. I think I might just have a look at the code for that function.

I confirmed my suspicions from looking at the code. I checked the glut 3 specification to see if this particular weirdness was documented. It wasn’t that I saw. Just in case anyone’s curious, the methods for glutSolidTeapot and glutWireTeapot call a function called teapot that looks like so…

static void
teapot(GLint grid, GLdouble scale, GLenum type)
{
float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
long i, j, k, l;

glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_MAP2_TEXTURE_COORD_2);
glPushMatrix();
glRotatef(270.0, 1.0, 0.0, 0.0);
glScalef(0.5 * scale, 0.5 * scale, 0.5 * scale);
glTranslatef(0.0, 0.0, -1.5);
for (i = 0; i < 10; i++) {
for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) {
for (l = 0; l < 3; l++) {
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 1)
q[j][k][l] *= -1.0;
if (i < 6) {
r[j][k][l] =
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 0)
r[j][k][l] *= -1.0;
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
if (l == 0)
s[j][k][l] *= -1.0;
if (l == 1)
s[j][k][l] *= -1.0;
}
}
}
}
glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2,
&tex[0][0][0]);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&p[0][0][0]);
glMapGrid2f(grid, 0.0, 1.0, grid, 0.0, 1.0);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&q[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
if (i < 6) {
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&r[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&s[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
}
}
glPopMatrix();
glPopAttrib();
}

You’ll notice that it does in fact use glTranslate, glRotate, AND glScale WITHOUT anywhere setting the matrix to GL_MODELVIEW.

Anyway… just something to store away in the memory banks in case anyone else ever posts about problems like this.