PDA

View Full Version : Problem: Inverted lighting position



Kalle
08-04-2008, 01:23 PM
Since a couple of weeks, I've been trying to learn OpenGL with the tutorials on http://www.videotutorialsrock.com. They are really great but this week, when I did a change of system, I got a problem with the lighting. What I try to do is a situation similar to the one in lesson 4, but with a couple of different shapes. Almost everything works satisfactory, but the thing is that the lighting acts as if the light source position would have been spacially inverted. Insted of comming from the top right, it comes from the left and below. What am I doing wrong?

I submit the code for the program beneath.

main file:



#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include <math.h>

//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif


#include "shapedrawer.h"

using namespace std;

float _rotAngle = 0.0f;
float _camAngle = 0.0f;


//Called when a key is pressed
void handleKeypress(unsigned char key, //The key that was pressed
int x, int y) { //The current mouse coordinates
switch (key) {
case 27: //Escape key
exit(0); //Exit the program
break;
case 'j':
_camAngle+=5.0f;
glutPostRedisplay();
break;
case 'k':
_camAngle-=5.0f;
glutPostRedisplay();
break;
case 'l':
if(glIsEnabled(GL_LIGHTING))
glDisable(GL_LIGHTING);
else
glEnable(GL_LIGHTING);
break;
}
}

//Initializes 3D rendering
void initRendering() {
//Makes 3D drawing work when something is in front of something else
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);

//glShadeModel(GL_FLAT);
glShadeModel(GL_SMOOTH);
glClearColor(0.7f, 0.9f, 0.8f, 1.0f);

}

//Called when the window is resized
void handleResize(int w, int h) {
//Tell OpenGL how to convert from coordinates to pixel values
glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective

//Set the camera perspective
glLoadIdentity(); //Reset the camera
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}

//Draws the 3D scene
void drawScene() {
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glTranslatef(0.0f, 0.0f , -5.0f);

glRotatef(15.0f, 1.0f, 0.0f, 0.0f);
glRotatef(-_camAngle, 0.0f, 1.0f, 0.0f);

GLfloat ambientColor[] = {0.2f, 0.2f, 0.2f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);


GLfloat light0position[] = {4.0f, 4.0f, 0.0f};
GLfloat light0ambientColor[] = {0.0f, 0.0f, 0.0f, 1.0f};
GLfloat light0diffuseColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat light0specularColor[] = {1.0f, 1.0f, 1.0f, 1.0f};

glLightfv(GL_LIGHT0, GL_POSITION, light0position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0ambientColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0diffuseColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0specularColor);


//GLfloat matSpecColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
//GLfloat matEmColor[] = {0.0f, 0.0f, 0.0f, 1.0f};
//glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
//glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpecColor);
//glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matEmColor);


//pyramid
glPushMatrix();
glColor3f(0.0f, 0.6f, 0.0f);
drawPyramid(1);
glPopMatrix(); //End of pyramid


//sphere
glPushMatrix();
glTranslatef(0.5f, 0.5f, 0.5f);
glColor3f(0.2f, 0.6f, 0.5f);
drawSphere(0.3,20,40);
glPopMatrix();


//cone
glPushMatrix();
glTranslatef(-1.0f, 0.0f, 1.0f);
glColor3f(0.7f, 0.7f, 0.4f);
drawCone(0.2,0.7,20);
glPopMatrix();

glutSwapBuffers(); //Send the 3D scene to the screen
}

void update(int value) {
_rotAngle += 3.0f;

if (_rotAngle >= 360) {
_rotAngle -= 360;
}

_camAngle += 0.5f;

if (_camAngle >= 360) {
_camAngle -= 360;
}

glutPostRedisplay();
glutTimerFunc(25, update, 0);
}

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


//Initialize GLUT
glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 800); //Set the window size

//Create the window
glutCreateWindow("Kalles OpenGL-skola");
initRendering(); //Initialize rendering

//Set handler functions for drawing, keypresses, and window resizes
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutReshapeFunc(handleResize);

glutTimerFunc(25, update, 0);
glutMainLoop(); //Start the main loop. glutMainLoop doesn't return.
return 0; //This line is never reached
}



Helping functions to draw various shapes:



#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include <math.h>

//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#include "shapedrawer.h"

using namespace std;


//sphere drawing function
static void sphericalToCart(double r, double theta, double phi, float x[3]) {

x[0] = r*sin(theta)*sin(phi);
x[1] = r*cos(theta);
x[2] = r*sin(theta)*cos(phi);

}

static void cylindricalToCart(double rho, double phi, double z, float x[3]) {

x[0] = rho*sin(phi);
x[1] = z;
x[2] = rho*cos(phi);
}

void drawCone(double radius, double height, int Nlong) {

double phi = 0.0;
double dPhi = (2*M_PI)/Nlong;
float x1[3], x2[3];
float top [] = {0.0f, height/2, 0.0f};

glBegin(GL_TRIANGLE_FAN);

glNormal3f(top[0], top[1], top[2]);

for(int i=0; i<Nlong; i++) {

phi = i*dPhi;

cylindricalToCart(radius, phi, -height/2, x1);
cylindricalToCart(radius, phi+dPhi, -height/2, x2);

//glBegin(GL_TRIANGLES);



glVertex3f(top[0], top[1], top[2]);
glNormal3f(x1[0], (float)(radius*radius/height), x1[2]);
glVertex3f(x1[0], x1[1], x1[2]);
glNormal3f(x2[0], (float)(radius*radius/height), x2[2]);
glVertex3f(x2[0], x2[1], x2[2]);


}
glEnd();
}

void drawSphere(double radius, int Nlat, int Nlong) {

double theta = 0.0;
double phi = 0.0;
double dTheta = M_PI/Nlat;
double dPhi = (M_PI*2)/Nlong;
float x1[3],x2[3],x3[3],x4[3];

for(int i=0; i<Nlat; i++) {

theta = i*dTheta;

for(int j=0; j<Nlong; j++) {

phi = j*dPhi;

sphericalToCart(radius, theta, phi, x1);
sphericalToCart(radius, theta, phi + dPhi, x2);
sphericalToCart(radius, theta + dTheta, phi, x3);
sphericalToCart(radius, theta + dTheta, phi + dPhi, x4);

glBegin(GL_QUADS);
//glNormal3f(x1[0]+x4[0], x1[1]+x4[1], x1[2]+x4[2]);
glNormal3f(x1[0], x1[1], x1[2]);
glVertex3f(x1[0], x1[1], x1[2]);
glNormal3f(x2[0], x2[1], x2[2]);
glVertex3f(x2[0], x2[1], x2[2]);
glNormal3f(x4[0], x4[1], x4[2]);
glVertex3f(x4[0], x4[1], x4[2]);
glNormal3f(x3[0], x3[1], x3[2]);
glVertex3f(x3[0], x3[1], x3[2]);
glEnd();

}
}

}


void drawPyramid(double side) {

glPushMatrix();

glScalef(side,side,side);

glBegin(GL_TRIANGLES);

//bottom face
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(-0.5f, -0.2041f, -0.2887f);
glVertex3f(0.5f, -0.2041f, -0.2887f);
glVertex3f(0.0f, -0.2041f, 0.5774f);

// back face
glNormal3f(0.0f, 2.041f, -5.774f);
glVertex3f(-0.5f, -0.2041f, -0.2887f);
glVertex3f(0.5f, -0.2041f, -0.2887f);
glVertex3f(0.0f, 0.6124f, 0.0f);

// right face
glNormal3f(0.5f, 0.2041f, 0.2887f);
glVertex3f(0.5f, -0.2041f, -0.2887f);
glVertex3f(0.0f, -0.2041f, 0.5774f);
glVertex3f(0.0f, 0.6124f, 0.0f);

// left face
glNormal3f(-0.5f, 0.2041f, 0.2887f);
glVertex3f(-0.5f, -0.2041f, -0.2887f);
glVertex3f(0.0f, -0.2041f, 0.5774f);
glVertex3f(0.0f, 0.6124f, 0.0f);

glEnd();

glPopMatrix();
}



Screenshot:
http://home.student.uu.se/kalj0193/bilder/Screenshot.png

dletozeun
08-04-2008, 01:39 PM
I see that you apply several transformations to your scene. Are you sure of how your light is transformed? Don't forget that all transformations applied above the line that sets the light position, affects this last one.

EDIT:

is the screenshot for camAngle = 0.0 ?

Komat
08-04-2008, 01:53 PM
One suspicious thing I found in your code.



GLfloat light0position[] = {4.0f, 4.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_POSITION, light0position);


The GL_POSITION expects four float values instead of three you are providing (the light position is expressed in homogeneous coordinates). Because of this it will fetch a undefined value behind the end of the light0position array. Depending on the compiler and compilation options you are using, the undefined value might be anything, possibly even a negative value which might explain the unexpected direction.

Kalle
08-05-2008, 12:22 AM
I see that you apply several transformations to your scene. Are you sure of how your light is transformed? Don't forget that all transformations applied above the line that sets the light position, affects this last one.

EDIT:

is the screenshot for camAngle = 0.0 ?

hm, perhaps not exactly. as you see it spins around, but i tried catching it there.


One suspicious thing I found in your code.



GLfloat light0position[] = {4.0f, 4.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_POSITION, light0position);


The GL_POSITION expects four float values instead of three you are providing (the light position is expressed in homogeneous coordinates). Because of this it will fetch a undefined value behind the end of the light0position array. Depending on the compiler and compilation options you are using, the undefined value might be anything, possibly even a negative value which might explain the unexpected direction.

This was it. Of course this error was really stupid and I can't understand how i missed it. Thanks for pointing it out!