Strange behavoir with Light + rotation

Hi all!
I’ve just started OGL coding with C++ and have created a simple scene with one light so far…
Now when i rotate the object with glRotatef the light seems to go up and down in a weird order but I want it to stay the same.
By what is this caused? What am I doing wrong?

Thanks in advance,
PureSpider

When you rotate (or more generally, transform) the object, you affect the modelview matrix. Then all objects defined after this transformation are affected by this one, including the opengl lights when you set their position.

So to not transform the light position, just set its postion before your rotation or use functions like glPushMatrix/glPopMatrix like this:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// set transformations
// draw objects
glPushMatrix(GL_MODELVIEW); // push under the stack the current modeview matrix
glLoadIdentity(); // reset all transformations
//draw your light
glPopMatrix(GL_MODELVIEW); // pop the last pushed modelview matrix to restore it as the current modelview matrix.

Thanks for your answer!

I’m having a little spin animation currently… Would that be the same approach to not change the lights? Just set their position before each transform action?

Like I said, yes, or use push/pop functions when it is more complicated.

Eh sorry but now I’m lost =(
This is my draw code I currently have:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glViewport(0, 0, w, h);

gluPerspective(45.0f, 1.0f * w / h, 1.0f, 100.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();

gluLookAt(
	0.0f, 15.0f, 30.0f,
	0.0f, 5.0f, 0.0f,
	0.0f, 1.0f, 0.0f
);

glRotatef(thetaup, 1.0f, 0.0f, 0.0f);
glRotatef(theta, 0.0f, 1.0f, 0.0f);

drawpolyshape();

SwapBuffers( hDC );

Lights are set only once in the window init function with:

glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 25.0f);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 75.0f);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

glEnable(GL_LIGHT0);

What do I need to change in that piece of code?
Sorry for beeing so noobish… =/

So with this code, the light is moving? What is the value of “LightPosition” ?

Yes it is, probably because I only set the position once and not on every transition…
Position is
float LightPosition[] = {0.0f, 0.0f, 10.0f, 1.0f};

OK, apparently it was also not clear to me.

In your code, you set once, in the init function the light position. Then you compute some transformations but never set the light position again in the draw function (where you do transformations). And I have noticed that in this case, the light is transformed by the modelview matrix even if you don’t put its position after setting transformations. (I hope I am clear :slight_smile: )

May be it is an undefined behavior since on my computer it is like I put glLight*(GL_POSITION…) at the end of all transformations. Don’t know if it os in the gl spec.

In conclusion, to make your application always working, just set the light position where you need in the goemetric transformations routine.

In your case:


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();

gluLookAt(
	0.0f, 15.0f, 30.0f,
	0.0f, 5.0f, 0.0f,
	0.0f, 1.0f, 0.0f
);

// the light position here, will only be affected by the lookAt transformation.
glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);

// transform your objects here
glRotatef(thetaup, 1.0f, 0.0f, 0.0f);
glRotatef(theta, 0.0f, 1.0f, 0.0f);

drawpolyshape();

SwapBuffers( hDC );

Had it that way… but changed it back because if I do it like that the light still goes bright and dark if I do the transitions and additionally only is a small spot at the bottom of the model =/
Would the compiled exe help fixing this?

Yes the whole code, may help me I think but not an exe (I am on linux, but I can compile it myself if it is not too big).

http://nopaste.org/p/a4L6GPvNA here yah go :slight_smile:

Your code is only for Windows since you use win32 to create the gl window. However I have quickly translated it in glut, to run it on linux.

I have noticed that you set a spotLight and it seems like you don’t define it completly. I mean, you set the spot exponent and cutoff but not its direction ( use the GL_SPOT_DIRECTION enum in glLight). So the light is surely pointing in the wrong direction.

Moreover, you enable lighting but, you don’t set normals on your quads. Lighting needs vertex normals.

I have much simplified your code and set an omni light instead of a spotlight. Rotation is not the same too, but look at this code snippet and compile it. It may help you:


#include <stdlib.h>
#include <GL/glut.h>

using namespace std;

struct XYZ
{
	float x;
	float y;
	float z;
};

bool quit = false;

float diffuseLight[] =
{ 0.8f, 0.8f, 0.8f, 1.0f };
float specularLight[] =
{ 1.0f, 1.0f, 1.0f, 1.0f };
float LightPosition[] =
{ 0.0f, 100.0f, 0.0f, 1.0f };
float local_view[] =
{ 0.0 };

float theta = 0.0f;
float thetaup = 0.0f;
float smallest_y = 0.0f;

int w = 600;
int h = 600;

int t, p;

void drawpolyshape(void)
{

	glColor3f(1.0f, 1.0f, 0.0f);
	
	glBegin(GL_QUADS);
	glNormal3f(0.0, 1.0, 0.0);
	glVertex3f(-10.0f, smallest_y, 10.0f);
	glNormal3f(0.0, 1.0, 0.0);
	glVertex3f(10.0f, smallest_y, 10.0f);
	glNormal3f(0.0, 1.0, 0.0);
	glVertex3f(10.0f, smallest_y, -10.0f);
	glNormal3f(0.0, 1.0, 0.0);
	glVertex3f(-10.0f, smallest_y, -10.0f);
	glEnd();

	glBegin(GL_QUADS);
	glNormal3f(0.0, -1.0, 0.0);
	glVertex3f(-10.0f, smallest_y, -10.0f);
	glNormal3f(0.0, -1.0, 0.0);
	glVertex3f(10.0f, smallest_y, -10.0f);
	glNormal3f(0.0, -1.0, 0.0);
	glVertex3f(10.0f, smallest_y, 10.0f);
	glNormal3f(0.0, -1.0, 0.0);
	glVertex3f(-10.0f, smallest_y, 10.0f);
	glEnd();
}

//------------------------------------------------------------	Reshape()
void OnReshape(int w, int h)
{
	// prevent a division by zero when minimising the window
	if (h == 0)
		h = 1;

	// set the drawable region of the window
	glViewport(0, 0, w, h);

	// set up the projection matrix 
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// just use a perspective projection
	gluPerspective(45.0f, 1.0f * w / h, 1.0f, 100.0f);

	// go back to modelview matrix so we can move the objects about
	glMatrixMode(GL_MODELVIEW);
}

//------------------------------------------------------------	Draw()
//
void OnDraw()
{
	if (theta >= 360.0f)
		theta = 0.0f;

	theta += 0.1;
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	gluLookAt(0.0f, 15.0f, 30.0f, 0.0f, 5.0f, 0.0f, 0.0f, 1.0f, 0.0f);
	
	glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
	
	glRotatef(theta, 0.0f, 0.0f, 1.0f);
	drawpolyshape();

	glutSwapBuffers();
	glutPostRedisplay();
}

//------------------------------------------------------------	OnInit()
//
void OnInit()
{
	glClearColor(0.0, 0.0, 0.0, 1.0);// Clear the buffer to this color.
	glShadeModel(GL_FLAT);

	glEnable(GL_CULL_FACE);

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING); // Enable lighting.

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glClearDepth(1.0f);

	// Set light information
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
	glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
	glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
	glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

	// Enable light
	glEnable(GL_LIGHT0);

	// Set up the material information for objects
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	glMaterialfv(GL_FRONT, GL_SPECULAR, specularLight);
	glMateriali(GL_FRONT, GL_SHININESS, 128);
}

//------------------------------------------------------------	OnExit()
//
void OnExit()
{
}

//------------------------------------------------------------	main()
//
int main(int argc, char** argv)
{

	// initialise glut
	glutInit(&argc, argv);

	// request a depth buffer, RGBA display mode, and we want double buffering
	glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE);

	// set the initial window size
	glutInitWindowSize(640, 480);

	// create the window
	glutCreateWindow("A basic glut example");

	// set the function to use to draw our scene
	glutDisplayFunc(OnDraw);

	// set the function to handle changes in screen size
	glutReshapeFunc(OnReshape);

	// run our custom initialisation
	OnInit();

	// set the function to be called when we exit
	atexit(OnExit);

	// this function runs a while loop to keep the program running.
	glutMainLoop();
	return 0;
}



It is running with glut. I hope, you have the library installed. Then compile it adding -lglut in the linker to link to the glut library.

Oh yes it works :slight_smile:
Thanks!

Now I have another question…
I want to draw one of my shapes “dotted”.
I figured that can be done with stipples, I just couldn’t get around how… =/

Nevermind, just managed to do it :slight_smile:

Ok, great :slight_smile:

For polygon stipple, I am not well informed about this, you should create another thread.

I have found these insteresting links:

http://www.codeproject.com/KB/openGL/OpenGLStipplePolygon.aspx
http://fly.srk.fer.hr/~unreal/theredbook/chapter02.html

I think you have already found these ones.

Yep I have, thanks :slight_smile:

€dit: Another question though… how to get keyboard inputs with the GLUT window?