move model and light but model gets 'out' of light

Hi,

I’m fairly new to openGL and have a problem with the light and a model. The program searches for a face and then with points on the face it calculates a model. Each frame I reinitialize the light at the point where I draw a circle (right of the model). But when I move my head (and thus the model and light) it seems like the light doesn’t reach the model (on the left side) or that it light the entire model (on the right side). See a movie of screencaptures at http://staff.science.uva.nl/~aazcarat/openGL/
Does anyone know what the problem could be?

I already had a similar question in this post:
http://www.opengl.org/discussion_boards/…6143#Post256143
The files mentioned in this ‘old’ post are already removed.

Thanks in advance for the help.

Here is how I initialize the light:

float lightX = (minX + maxX)/2 + 150.0f;
float lightY = (minY + maxY)/2 + 0.0f;
float lightZ = (minZ + maxZ)/2 + 0.0f;
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
float noAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
float whiteDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
float global_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
float position[] = {lightX, lightY, lightZ, 1.0f};
float ambPos[] = {150.0f,0.0f,0.0f,1.0f};
glLightfv(GL_LIGHT0, GL_AMBIENT, noAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, whiteDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);

minX, maxX, minY, maxY, minZ and maxZ are the min and max coordinates values of the model

It almost looks as if light0 is set up as a spotlight. Your code seems to specify a omni-directional point light however.
I can’t tell what’s wrong without more code, but it looks like it is better to set up a directional light source to get what you want.

Here’s code to simulate typical outdoor sun-lighting:

const float p[4] = {-sunvec.x, -sunvec.y, -sunvec.z, 0.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, suncolor);
glLightfv(GL_LIGHT0, GL_POSITION, p);
glEnable(GL_LIGHT0);

Here, “sunvec” is the sunlight direction vector pointing down from the sky. We invert the vector to effectively turn it into a position, and tack the 0.0 at the end to make it non-positional. Essentially the 0.0 causes the light position to be infinitely far away, effectively resulting into directional lighting (while the parameter is called GL_POSITION, it’s essentially a plane equation).

You may want to look at this page to rule out other things: http://www.sjbaker.org/steve/omniv/opengl_lighting.html

PS, it would be a bigger achievement to put a believable expression on Jan-Peter’s face without CGI. :smiley:

Thanks for the reply remdul.

I’m getting lost again. What I’m trying to do is to specify a light (from a lightbulb so a spotlight sounds correct right?) that is relative to my model. I read the following at: http://www.opengl.org/resources/faq/technical/lights.htm

*  How can I make my light stay fixed relative to my scene? How can I put a light in the corner and make it stay there while I change my view?

    Set the view transform. Set the light position //glLightfv(GL_LIGHT_POSITION,…) Send down the scene or model geometry. Swap buffers. 

I’m doing this:
glMatrixMode( GL_MODELVIEW);
glPushMatrix();
InitScene();
Mask->Draw(trans); -> here i initialize the light as mentioned above and draw the model
glPopMatrix();
and then swapbuffers

The steps that I do to get a light relative to the model are correct, right? (first the light and then draw)

I made two new videos which are available at:
http://staff.science.uva.nl/~aazcarat/openGL/
0.0f is with position[] = {lightX, lightY, lightZ, 0.0f};//light at ‘infinity’ and direction is x,y,z
1.0f is with position[] = {lightX, lightY, lightZ, 1.0f};//light at x,y,z position and omnidirectional

Everything I mentioned here is correct, right? Or am I missing something?

As you can see in the videos it works ‘funny’.

I cannot give any code as it is not mine and it is not openly available, I have to improve the program. Sorry.

Thanks for the help!

P.S: You’re right! It is more difficult to put a believable expression on his face without CGI :slight_smile:

Maybe the problem is that the vector is from x,y,z to 0,0,0 and not from x,y,z to centerOfModel. I don’t have time to look into it now but I will report back on it tomorrow.

FWIW - this is just a guess …

From your avi’s it looks like the light source is NOT moving with the model. If it was, lighting on the face would not change. To make the light source move with the model you must call glLightfv with the ‘position’ parameter AFTER you call the glTranslate(s) that move the face.

I also think that somehow the light is not moving as I want. I call the glLightfv just before I draw the model so there aren’t any glTranslate(s) between them.

Steps: the model is in a array/vector, I recalculate some stuff (actually add triangles) and then from the coordinates of these triangles I calculate the average coordinates (will be more or less in the middle of the model) and then use these coordinates to initialize the light.

code exactly as it appears in file:

//triangles have been calculated thus light can be initialized
float lightX = 150.0f;//totalX/totalCounter + 150.0f;
float lightY = 0.0f;//totalY/totalCounter + 0.0f;
float lightZ = 0.0f;//totalZ/totalCounter + 0.0f;
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
float noAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
float whiteDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
float global_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
float position[] = {lightX, lightY, lightZ, 1.0f};
float ambPos[] = {150.0f,0.0f,0.0f,1.0f};
glLightfv(GL_LIGHT0, GL_AMBIENT, noAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
//get the ‘color’ of the face to ‘apply’ to texture
GLdouble pos3D_x, pos3D_y, pos3D_z;
GLdouble model_view[16];
glGetDoublev(GL_MODELVIEW_MATRIX, model_view);
GLdouble projection[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
gluProject(totalX/totalCounter,totalY/totalCounter,totalZ/totalCounter,model_view,projection,viewport,&pos3D_x,&pos3D_y,&pos3D_z);
int nWidth = 1;
int nHeight = 1;
GLubyte pRGB[3];
glReadPixels( pos3D_x, pos3D_y, nWidth, nHeight, GL_RGB, GL_UNSIGNED_BYTE, (void *)pRGB);
float skinRed = pRGB[ 0 ]/255.0;
float skinGreen = pRGB[ 1 ]/255.0;
float skinBlue = pRGB[ 2 ]/255.0;
glColor4f(skinRed,skinGreen,skinBlue,1.0f);
glBegin(GL_TRIANGLES);
for(int i=0;i<triangles2.size();i++)
{//three vertices
int a = triangles2[i].x;
int b = triangles2[i].y;
int c = triangles2[i].z;
//vertice one
glNormal3f(vertices2[a].x+normals2[a].x,vertices2[a].y+normals2[a].y,vertices2[a].z+normals2[a].z);
glTexCoord2d(texCoords2[a].x,texCoords2[a].y);
glVertex3f(vertices2[a].x,vertices2[a].y,vertices2[a].z);
//vertice two glNormal3f(vertices2[b].x+normals2[b].x,vertices2[b].y+normals2[b].y,vertices2[b].z+normals2[b].z);
glTexCoord2d(texCoords2[b].x,texCoords2[b].y);
glVertex3f(vertices2[b].x,vertices2[b].y,vertices2[b].z);
//vertice three
glNormal3f(vertices2[c].x+normals2[c].x,vertices2[c].y+normals2[c].y,vertices2[c].z+normals2[c].z);
glTexCoord2d(texCoords2[c].x,texCoords2[c].y);
glVertex3f(vertices2[c].x,vertices2[c].y,vertices2[c].z);
}
glEnd();
glBegin(GL_LINE_LOOP);
glColor3f(0.0,0.0,1.0);
//draw circle at light position
glEnd();

I have left out the code where the triangles are calculated and where the circle for the light is drawn.
As you see there are no glTranslate(s) between the light initialization and the drawing of the model (I’m not even sure if glTranslate is used to calculate the new position).

If I want my light to come from a point this is how I should initialize it, right? With centerX,centerY,centerZ the center of the model and lightX,lightY,lightZ the ‘offset’ of the point. Or am I missing something here?

float position[] = {lightX+centerX, lightY+centerY, lightZ+centerZ, 1.0f};
glLightfv(GL_LIGHT0, GL_AMBIENT, noAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);

havent read the whole post but you should know that even if no glTranslate is used your light position is transformed by your current modelview matrix. either you have direct light position in eyespace then modelview matrix is identity or you have a zero position (at the origin) and move your light with the modelview matrix.

[b]code 1:
// absolute position
GLfloat lightpos[4] = { 4.0f, 0.0f, 20.f, 1.0f };
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightv(); // position not transformed

code 2:
// position at origin
GLfloat lightpos[4] = { 0.0f, 0.0f, 0.f, 1.0f };
glLightv(); // position transformed by modelview matrix[/b]

I think I’m doing it like in code 2.
I changed the order of things a bit, now at each frame these are the steps I take (at least the steps that are interesting for me):
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
InitScene();
–> initLights();//light is enabled and initialized at centerModel+offset with w=1.0f(point light)
–> glEnable( GL_TEXTURE_2D );
–> glEnable(GL_COLOR_MATERIAL);
–> glEnable(GL_BLEND);
–> glDisable(GL_DEPTH_TEST);
drawMask();//where the mask is drawn with glVertex and glNormal
glPopMatrix();

So first matrixMode is taken as GL_MODELVIEW and the matrix is saved, then ‘inside’ initScene() initLights() is called that enables and initializes the lights and in initScene() also the texture, color_material and blend are enabled and depth_test disabled (among other things). Then the mask is drawn and then the top matrix is ‘poped’.

Another thing is that if I don’t disable the depth_test I don’t see the model at all. Maybe this has something to do with it or gives you an idea of what could be the problem?

‘Another thing is that if I don’t disable the depth_test I don’t see the model at all.’
weird. should not affect light in general.

you push matrix thats good but the current modelview matrix is probably set up for the model you are about to render. specifying the light position will still be modified by the matrix. in total you modify the position 2 times, by <lightX+centerX, lightY+centerY, lightZ+centerZ> and by the modelview matrix. try to set glLoadIdentity() after glPushMatrix() see how it goes.

With this: ‘Another thing is that if I don’t disable the depth_test I don’t see the model at all.’
I don’t mean that it affects the lighting, the model is just not drawn. I mentioned it because maybe it could give you a ‘new idea’ or ‘extra insight’ in the problem. I already thought it had nothing to do with the lighting problem but mentioned it just in case it did.

About glLoadIdentity(), I also thought it could be that the current matrix could be the ‘wrong’ one. So I already did check this possibility but it does not change anything (at least the lighting is still wrong).

In the txt file (at http://staff.science.uva.nl/~aazcarat/openGL)) you can see the openGL calls of the program till I close it. Maybe you can see something here what I miss or is set wrong (I think it is a small thing which I keep missing and it bugs me as hell!!).

txt file explanation:

The important part is from this point (at least what I think): BVRTTrackerWindow::Draw()

Each tab means the calls inside the method. So after this line: BVRTTrackerWindow::Draw() there is a tab (more) than at the current line thus everything under this is called inside BVRTTrackerWindow::Draw() until you see ‘end BVRTTrackerWindow::Draw()’ and there is a tab less.

I hope you can see something (and that you understand my explanation of the txt file).

unfortunately have no time to glance through the txt file but i think you should place your light on a constant position for now and play with the settings a little before starting moving it around. hard to tell what the problem is.
see this lighting sample for more information: http://www.codesampler.com/oglsrc/oglsrc_5.htm#ogl_lighting