PDA

View Full Version : Strange behavoir with Light + rotation



PureSpider
10-09-2008, 03:29 AM
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

dletozeun
10-09-2008, 04:43 AM
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.

PureSpider
10-09-2008, 04:55 AM
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?

dletozeun
10-09-2008, 04:58 AM
Like I said, yes, or use push/pop functions when it is more complicated.

PureSpider
10-09-2008, 05:07 AM
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... =/

dletozeun
10-09-2008, 05:50 AM
So with this code, the light is moving? What is the value of "LightPosition" ?

PureSpider
10-09-2008, 06:00 AM
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};

dletozeun
10-09-2008, 06:09 AM
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 :) )

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 );

PureSpider
10-09-2008, 06:15 AM
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?

dletozeun
10-09-2008, 06:20 AM
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).

PureSpider
10-09-2008, 06:27 AM
http://nopaste.org/p/a4L6GPvNA here yah go :)

dletozeun
10-09-2008, 07:33 AM
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(&amp;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.

PureSpider
10-09-2008, 12:27 PM
Oh yes it works :)
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 :)

dletozeun
10-09-2008, 04:30 PM
Ok, great :)

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.

PureSpider
10-10-2008, 04:46 AM
Yep I have, thanks :)

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