Position Lights :: Fixed relative to scene... How?

Edit 15/03/05 : Question answered, code updated.

I’ve been going insane over this little problem, which is that I can’t fix a GL_POSITION light at a point relative to my scene.

The light seems to transform with objects. However I don’t think it’s moving with the camera. I want the light to stay in a fixed point in the scene, independent of everything else.

Here’s a screencap of the problem: Position Lights
In this vid, as the cubes rotate the sides should change lightness as they get closer/further from the light.

And here’s the code:

 

#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

static GLfloat spin = 0.0;
static GLfloat osc = 0.0;
static GLfloat i = 0.0;
static GLfloat j = 0.15;	//Increment: Adjusts horse bobbing speed
static GLfloat k = 6.28;	
static GLfloat l = 0.8;		//Increment: Adjusts rotation speed

GLint height = 50, width = 50;
GLint globalX, globalY;



// COORDINATE COLUMNS ::		 X		 Y		 Z
// base coordinates (left) 
static GLint baseverts[] =	{	-50,	-40,	 50,		//point 1
								 50,	-40,	 50,		//point 2
								 50,	-30,	 50,		//etc
								-50,	-30,	 50,
								-50,	-40,	-50,
								 50,	-40,	-50,
								 50,	-30,	-50,
								-50,	-30,	-50
							};

// base coordinates (left) 
static GLint topverts[] =	{	-50,	30,		50,		//point 1
								 50,	30,		50,		//point 2
								 50,	40,		50,		//etc
								-50,	40,		50,
								-50,	30,		-50,
								 50,	30,		-50,
								 50,	40,		-50,
								-50,	40,		-50
							};



// box 1 coordinates (left) 
static GLint box1verts[] =	{	-50,	-10,	 10,		//point 1
								-30,	-10,	 10,		//point 2
								-30,	 10,	 10,		//etc
								-50,	 10,	 10,
								-50,	-10,	-10,
								-30,	-10,	-10,
								-30,	 10,	-10,
								-50,	 10,	-10
							};


// box 2 coordinates (right)
static GLint box2verts[] =	{	 30,	-10,	 10,		//point 1
								 50,	-10,	 10,		//point 2
								 50,	 10,	 10,		//etc
								 30,	 10,	 10,
								 30,	-10,	-10,
								 50,	-10,	-10,
								 50,	 10,	-10,
								 30,	 10,	-10
							};

// box 3 coordinates (middle) 
static GLint box3verts[] =	{	-10,	 -30,	10,		//point 1
								 10,	 -30,	10,		//point 2
								 10,	 30,	10,		//etc
								-10,	 30,	10,
								-10,	 -30,	-10,
								 10,	 -30,	-10,
								 10,	 30,	-10,
								-10,	 30,	-10
							};

// NORMALS ::					X		Y		Z
static GLfloat normals[]=	{	-1.0,	-1.0,	1.0,
								1.0,	-1.0,	1.0,		
								1.0,	1.0,	1.0,		
								-1.0,	1.0,	1.0,
								-1.0,	-1.0,	-1.0,
								1.0,	-1.0,	-1.0,		
								1.0,	1.0,	-1.0,
								-1.0,	1.0,	-1.0};



// COLOUR COLUMNS ::			R		G		B
static GLfloat colors[]=	{	1.0,	0.0,	0.0,		//point 1 colors
								0.0,	1.0,	0.0,		//etc
								0.0,	0.0,	1.0,
								0.5,	0.0,	0.0,
								0.0,	0.5,	0.0,
								0.0,	0.0,	0.5,
								1.0,	1.0,	1.0,
								1.0,	0.0,	1.0};



//cube indices refs in one array

//					3___________2
//				   /		   /|
//				  /			  /	|
//			    7/___________/6	| RIGHT
//				 |	|		|   |
//				 |	0 _		|   |1
//				 |  /		|  /
//				 | 			| /
//				 |__________|/
//				4	FRONT	 5



static GLubyte boxIndices[]= {4,5,6,7, 1,2,6,5, 0,1,5,4, 0,3,2,1, 0,4,7,3, 2,3,7,6};
GLfloat posone [] = { 80.0,	20.0, -80.0, 0.0 };
GLfloat colone [] = { 1.0, 0.0, 0.0 };

GLfloat postwo [] = { -80.0, 200.0, 80.0, 0.0 };
GLfloat coltwo [] = { 0.0, 1.0, 0.0 };


void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	GLdouble eyeX = globalX-(width/2);
	GLdouble eyeZ = cos(eyeX/width)*2000-1820;
	//printf("%4.2f
",eyeZ);
	
	gluLookAt(eyeX/2,globalY-30,eyeZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	glEnable(GL_LIGHTING);
	glLightfv(GL_LIGHT0, GL_COLOR, colone);
	glLightfv(GL_LIGHT1, GL_COLOR, coltwo);
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHT1);
	
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
    
	glColorPointer(3,GL_FLOAT,0,colors);
	
	
	
	
	

	
	
	glPushMatrix();
	
	
	glVertexPointer(3,GL_INT,0,baseverts);
	glNormalPointer(GL_FLOAT,0,normals);
	glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, boxIndices);
	glVertexPointer(3,GL_INT,0,topverts);
	glNormalPointer(GL_FLOAT,0,normals);
	glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, boxIndices);

	glRotatef(spin,0.0,1.0,0.0);
	


	// draw the lot at once
	glVertexPointer(3,GL_INT,0,box3verts);
	glNormalPointer(GL_FLOAT,0,normals);
	glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, boxIndices);
	

	
	glTranslatef(0.0,osc,0.0);
	glVertexPointer(3,GL_INT,0,box1verts);
	
	glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, boxIndices);
	glVertexPointer(3,GL_INT,0,box2verts);
	
	glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, boxIndices);


	glPopMatrix();
	
	
	glutSwapBuffers();


}

void oscDisplay(void)
{

	osc = sin(i)*20;
	i = i + j;
	if (i >k)
		i = 0;

	glutPostRedisplay();
	
}

void animDisplay(void)
{
	
	osc = sin(i)*20;
	i = i + j;
	if (i >k)
		i = 0;
	
	spin = spin + l;
	if (spin > 360.0)
		spin = spin - 360.0;
	
	glutPostRedisplay();
}


void spinDisplay(void)
{
	spin = spin + l;
	if (spin > 360.0)
		spin = spin - 360.0;

	glutPostRedisplay();
	
}









// Mouse Control :: Starts and stops animation
void mouse(int button, int state, int x, int y)
{
	switch (button)
	{
	case GLUT_LEFT_BUTTON:
		if (state == GLUT_DOWN)
			printf("Left Mouse Button Pressed:
	Horses Bobbing at increments of %f
",j);
			glutIdleFunc(oscDisplay);
		break;

		case GLUT_MIDDLE_BUTTON:
		if (state == GLUT_DOWN)
			printf("Middle Mouse Button Pressed:
	Horses Rotating at increments of %f
",l);
			glutIdleFunc(spinDisplay);
		break;

	case GLUT_RIGHT_BUTTON:
		if (state == GLUT_DOWN)
			printf("Right Mouse Button Pressed:
	Horses Bobbing at increments of %f
	Horses Rotating at increments of %f
",j,l);
			glutIdleFunc(animDisplay);
		break;
	default:
		break;
	
	}
}


void eyePosition(int x, int y)

{
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(80,1.0,1,1000);
 glMatrixMode(GL_MODELVIEW);
 glLightfv(GL_LIGHT0, GL_POSITION, posone);
 glLightfv(GL_LIGHT1, GL_POSITION, postwo);
 glutPostRedisplay();
 globalX = x;
 globalY = y;

}
void reshape(int w, int h)
{	
	width	= w;
	height	= h;	
	
	glMatrixMode(GL_MODELVIEW);
	
	glViewport(0,0,(GLsizei) w, (GLsizei) h);
	printf("Window Resized: Width=%d Height=%d
",w,h);
	glutPassiveMotionFunc(eyePosition);
	
			
}



int main(int argc, char** argv)
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );
	glutInitWindowSize(500,500);
	glutInitWindowPosition(100,100);
	glutCreateWindow("OpenGL Window");
	glutReshapeFunc(reshape);
	glutDisplayFunc(display);
	glutMouseFunc(mouse);
	glutMainLoop();
	return 0;
}

Any ideas? Thanks in advance.

glLightfv(GL_LIGHT0, GL_POSITION, position) is affected by current modelview matrix. Try to setup your light source position BEFORE any modelview matrix transformation… like

  
void display(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glLightfv(GL_LIGHT0, GL_POSITION, position);
// now you can setup view matrix (gluLookAt())

...
}

You also have a BIG error using opengl matrices. Please read this http://www.sjbaker.org/steve/omniv/projection_abuse.html

yooyo

yooyo thanks for your help… I made some changes to my code as you suggested (updated above) but I’m still getting the same problems. I admit I’m not 100% sure about the use of matrix modes (still learning)… just when I think I understand what they do it goes and does something completely unexpected!

How do I create the light outside of the transform matrix? At the moment it seems to be getting transformed with everything else, even with the changes.

Your eyePosition func is completly wrong. It should looks like:

  
int globalX, globalY;
void eyePosition(int x, int y)
{
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(80,1.0,1,1000);
 glMatrixMode(GL_MODELVIEW);
 globalX = x;
 globalY = y;
}

and in display func you need to do:

  
void display(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 GLfloat position[] = { 80.0, 50.0, -50.0, 1.0 };	 // 1.0 for spot or 0.0 for directional light
 glLightfv(GL_LIGHT0, GL_POSITION, position);
 gluLookAt(globalX-(width/2),globalY,-100.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
...

and you have to provide normal for each vertex if you want to see correct lighting. For your boxes, when face looks to -X vertex normal for all 4 vertices is (-1,0,0), +X -> (1,0,0), -Y -> (0,-1,0), +Y ->(0,1,0), -Z -> (0,0,-1), +Z ->(0,0,1). When you put all this data into vertex arrays, you’l see that vertex have 3 different normals depending on which face you render. So, box have 6 sides, each side has 4 vertices, each vertex has it’s position and it’s normal. 6sides*4 vertices = 24vertices for box.

yooyo

Thanks again for your help, I have made the corrections you suggested (updated in my original post) and have set up the face normals, and it’s looking better! The light is independent of the camera and geometry, remaining in a fixed position.

The only thing now is that the top faces of the boxes change shade, when I would have thought they would remain the same as these faces’ normals are always the same angle in relation to the light.

Do it on this way:

  
typedef struct tagVertex
{
 float pos[3];
 float normal[3];
 float color[3];
} tVertex;

// note that you will repeat some verices, but it this vertices are different because of it's normal is different
tVertex myBox[] =
{
{data for vertex 0},
{data for vertex 1},
...
{data for vertex 23}
};

unsigned int myBoxFaces[]=
{
 ... // fill indices to each face
};

...
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glColorPointer(3,GL_FLOAT,sizeof(tVertex),myBox[0].color);
glVertexPointer(3,GL_FLOAT,sizeof(tVertex),myBox[0].pos);
glNormalPointer(GL_FLOAT,sizeof(tVertex),myBox[0].normal);
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, myBoxFaces);

yooyo