Please, help me get this right.

I’ve created a simple red cube that you can look at in all directions and there’s also a light source in the direction (0, 1, 0.5). I can’t get the lighting correct. As you move around the cube different sides of it turns black and then gets lit again etc. Seems like the lighting source gets affected somehow by my movements, but I can’t figure out why. Can someone take a glance at the code below and tell me what I’m doing wrong?
BTW, if you go inside the cube, you can even se the some of the sides of the cube, even though I’m quite sure I’ve got the normals right, haven’t I?

#include <Gl/glut.h>

GLfloat modelview[16];

void display() {
GLfloat matProp[] = {1,0,0,0};
glMaterialfv(GL_FRONT, GL_SPECULAR, matProp );
glMaterialfv(GL_FRONT, GL_DIFFUSE, matProp);
glMaterialfv(GL_FRONT, GL_AMBIENT, matProp);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(modelview);
glBegin(GL_POLYGON);
glNormal3f(0,0,1);
glVertex3f(0,0,0);
glVertex3f(1,0,0); //front
glVertex3f(1,1,0);
glVertex3f(0,1,0);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(1,0,0);
glVertex3f(1,0,-1);
glVertex3f(1,1,-1); //right
glVertex3f(1,1,0);
glVertex3f(1,0,0);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(0,0,-1);
glVertex3f(1,0,-1);
glVertex3f(0,0,-1); //back
glVertex3f(0,1,-1);
glVertex3f(1,1,-1);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(-1,0,0);
glVertex3f(0,0,-1);
glVertex3f(0,0,0); //left
glVertex3f(0,1,0);
glVertex3f(0,1,-1);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(0,1,0);
glVertex3f(0,1,0); //top
glVertex3f(1,1,0);
glVertex3f(1,1,-1);
glVertex3f(0,1,-1);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(0,-1,0);
glVertex3f(0,0,0);
glVertex3f(0,0,-1); //bottom
glVertex3f(1,0,-1);
glVertex3f(1, 0, 0);
glEnd();

glutSwapBuffers();
}

void myReshape(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, width/(float) height, 0.01, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0.5,1, 0,0.5,-0.5, 0,1,0);
glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
}

void storeModelMatrix() {
glMultMatrixf(modelview);
glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
}

void Keyfunc(unsigned char key, int x, int y) {
switch (key) {
case ‘w’:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0, 0, 0.05);
storeModelMatrix();
glutPostRedisplay();
break;
case ‘s’:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0, 0, -0.05);
storeModelMatrix();
glutPostRedisplay();
break;
case ‘a’: glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(-2, 0, 1, 0);
storeModelMatrix();
glutPostRedisplay();
break;
case ‘d’: glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(2, 0, 1, 0);
storeModelMatrix();
glutPostRedisplay();
break;
case ‘z’: glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0, -0.05, 0);
storeModelMatrix();
glutPostRedisplay();
break;
case ‘x’: glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0, 0.05, 0);
storeModelMatrix();
glutPostRedisplay();
break;
case ‘n’: glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0.05, 0, 0);
storeModelMatrix();
glutPostRedisplay();
break;
case ‘m’: glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(-0.05, 0, 0);
storeModelMatrix();
glutPostRedisplay();
break;
}
}

void init() {
GLfloat specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat lightPosition[] = {0, 1, 0.5, 0.0};
glClearColor(0x87/(float) 0xFF, 0xCE/(float) 0xFF, 0xEB/(float) 0xFF, 0.0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_DEPTH_TEST);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_DIFFUSE, specular);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glShadeModel(GL_FLAT);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}

int main(int argc, char** argv) {
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutCreateWindow(“test”);
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutKeyboardFunc(Keyfunc);
init();
glutMainLoop();
}

Look’s like the hard way to rotate something…
But anyway you also rotating the light with your code, so the back of the cube will be black since the light is in front.

Look at some of my glut examples on my website:
http://www.angelfire.com/linux/nexusone/

glPushMatrix();
glTranslatef( 0.0, 0.0, -2.0);
glRotatef( spin, 1.0, 1.0, 0.0);
Draw_objects();
glPopMatrix();

spin varaible is now much to rotate the cube 0 to 360.
You can replace in your keyboard the matrix stuff with a simple variable of how much to rotate your cube.

Your code:

// Draw cube
glPushMatrix();
glTranslatef(…); adjust position in world.
glRotatef(…); rotate object.
note you can repeat the rotate command for each axis if needed.
glRotatef( x_rot, 1.0, 0.0, 0.0); // Rotate X axis only

glBegin(GL_POLYGON);
glNormal3f(0,0,1);
glVertex3f(0,0,0);
glVertex3f(1,0,0); //front
glVertex3f(1,1,0);
glVertex3f(0,1,0);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(1,0,0);
glVertex3f(1,0,-1);
glVertex3f(1,1,-1); //right
glVertex3f(1,1,0);
glVertex3f(1,0,0);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(0,0,-1);
glVertex3f(1,0,-1);
glVertex3f(0,0,-1); //back
glVertex3f(0,1,-1);
glVertex3f(1,1,-1);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(-1,0,0);
glVertex3f(0,0,-1);
glVertex3f(0,0,0); //left
glVertex3f(0,1,0);
glVertex3f(0,1,-1);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(0,1,0);
glVertex3f(0,1,0); //top
glVertex3f(1,1,0);
glVertex3f(1,1,-1);
glVertex3f(0,1,-1);
glEnd();

glBegin(GL_POLYGON);
glNormal3f(0,-1,0);
glVertex3f(0,0,0);
glVertex3f(0,0,-1); //bottom
glVertex3f(1,0,-1);
glVertex3f(1, 0, 0);
glEnd();

glPopMatrix();

// A bit of your keyboard routine
void Keyfunc(unsigned char key, int x, int y) {
switch (key) {
case ‘w’:
z_trans += 0.05;
glutPostRedisplay();
break;

Just repeat above for each movement.
Hope this is what your looking for

[This message has been edited by nexusone (edited 02-23-2003).]

the reason the inside of your cube is also lit is because the renderer uses the normals for the outside faces. Of course these are wrong for the INSIDE faces but the renderer doesnt know that.
Note that the squares that are lit on the outside are dark inside and the dark ones lit.

Ahhh, I see. Do you have any suggestions on how I shall do with the lighting so that it does the transformations in the modelviewmatrix? To me it would seem logical to put glLightfv(GL_LIGHT0, GL_POSITION, lightPosition) right after I’ve loaded my accumulated movements matrix into modelview like this:

void display() {
.
.
.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(modelview);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glBegin(GL_POLYGON);
.
.
.

Didn’t do any good though / I’m sure I’m doing some embarrasing obvious error.

Best regards,

Simon

While do accumulated movement by saving the model matrix works, do you not see the limitation you may have when you have multiple objects?

Here is something to try, you can place the you light position in the display routine:

glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glPushMatrix(); // Save lighting position in matrix()
// Draw Cube with accumulated matrix

glPopMatrix(); return matrix to before accumulated matrix state.

This may give do the trick, but still not sure why you rotating this way though and seems no advantage to do it so.

Originally posted by Seamoon:
[b]Ahhh, I see. Do you have any suggestions on how I shall do with the lighting so that it does the transformations in the modelviewmatrix? To me it would seem logical to put glLightfv(GL_LIGHT0, GL_POSITION, lightPosition) right after I’ve loaded my accumulated movements matrix into modelview like this:

void display() {
.
.
.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(modelview);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glBegin(GL_POLYGON);
.
.
.

Didn’t do any good though / I’m sure I’m doing some embarrasing obvious error.

Best regards,

Simon[/b]