Hello everybody,
this thread actually started in the Maths area, because I was sure, that my problem with lighting in OpenGL comes from some wrong normal calculation, but it seems like that is not the case. Thus I continue the thread here.
I load objects as .3ds models into my application. I already checked the CW or CCW orientation of the triangles, but it turned out that they are consistent. I calculate the normals from my model data ( which is also correct, since I use the same data to actually draw my models ) and then I try to add lighting ( ambient, diffuse and specular for now ).
My light is initially at position 0, 0, 0. When it is there, everything looks fine. The correct faces are lit up or not lit up according to their position/orientation.
This is how it looks when the light is at the origin and everything is fine ( the light is at the origin of the particle system ).
Now when I move my light in any direction, the faces start to flicker and sometimes wrong faces are lit up etc. Actually pretty much all the lighting messes up big time.
This is how it looks when the lighting is messed up.
And when I move the light even further away from the origin, the whole diffuse color ( which is the light component that messes up by the way ) disappears, and everything is lit only using the ambient color.
So,
this is how it looks now.
I don't know what could be causing this problem.
Here are the relevant code parts:
Part of my initialization code...
// enable texture mapping
glEnable ( GL_TEXTURE_2D );
// enable smooth shading
glShadeModel ( GL_SMOOTH );
// enable lighting
glEnable ( GL_LIGHTING );
// enable normalizing
glEnable ( GL_NORMALIZE );
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
// set background color
glClearColor ( 0.6f, 0.6f, 0.6f, 1.0f );
// depth buffer setup
glClearDepth ( 1.0f );
// initialize a light
float ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
float diffuse[] = { 1.0f, 0.0f, 0.0f, 1.0f };
float specular[] = { 12.0f, 12.0f, 12.0f, 12.0f };
lgt.init ( ambient, diffuse, specular );
lgt.toggle ( true );
}
My complete object::draw ( ) function...
void object::draw ( )
// draws the object normally to the screen
{
// reset the matrix
glLoadIdentity ( );
// position the camera
cam.update ( );
// update acceleration values
update_position ( );
// move and rotate to place the object
glTranslatef ( position.x, position.y, position.z );
glRotatef ( rotation.x, 1.0f, 0.0f, 0.0f );
glRotatef ( rotation.y, 0.0f, 1.0f, 0.0f );
glRotatef ( rotation.z, 0.0f, 0.0f, 1.0f );
// set up render modes
glColorMask ( 1, 1, 1, 1 );
glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f );
glDisable ( GL_BLEND );
glDisable ( GL_CLIP_PLANE0 );
glEnable ( GL_DEPTH_TEST );
glDisable ( GL_STENCIL_TEST );
if ( sphere_mapped == true )
// if the object is sphere mapped
{
// enable sphere mapping
glEnable ( GL_TEXTURE_GEN_S );
glEnable ( GL_TEXTURE_GEN_T );
}
else
// if the object is texture mapped
{
// disable shere mapping
glDisable ( GL_TEXTURE_GEN_S );
glDisable ( GL_TEXTURE_GEN_T );
}
// activate texture
surface_texture.activate ( );
// push the matrix
glPushMatrix ( );
// scale
glScalef ( size, size, size );
for ( int i = 0; i < actor.num_polygons; i++ )
// loop through each polygon
{
float vertex1[3], vertex2[3], vertex3[3];
// prepare vertex data
vertex1[0] = actor.vertex[actor.polygon.a ].x;
vertex1[1] = actor.vertex[actor.polygon.a ].y;
vertex1[2] = actor.vertex[actor.polygon.a ].z;
vertex2[0] = actor.vertex[actor.polygon.b ].x;
vertex2[1] = actor.vertex[actor.polygon.b ].y;
vertex2[2] = actor.vertex[actor.polygon.b ].z;
vertex3[0] = actor.vertex[actor.polygon.c ].x;
vertex3[1] = actor.vertex[actor.polygon.c ].y;
vertex3[2] = actor.vertex[actor.polygon.c ].z;
// get the face normal
get_face_normal ( actor.normal, vertex1, vertex2, vertex3 );
// multiply it by -1
actor.normal[0] *= -1;
actor.normal[1] *= -1;
actor.normal[2] *= -1;
cgGLSetParameter3f ( vertexPosition, vertex1[0], vertex1[1], vertex1[2] );
cgGLSetParameter3f ( vertexNormal, actor.normal[0], actor.normal[1], actor.normal[2] );
// begin drawing polygon
glBegin ( GL_TRIANGLES );
// activate face normal
glNormal3f ( actor.normal[0], actor.normal[1], actor.normal[2] );
// draw first vertex
glTexCoord2f ( actor.mapcoord[actor.polygon.a].u, actor.mapcoord[actor.polygon.a].v );
glVertex3f ( actor.vertex[actor.polygon.a ].x, actor.vertex[actor.polygon.a ].y, actor.vertex[actor.polygon.a ].z );
// draw second vertex
glTexCoord2f ( actor.mapcoord[actor.polygon.b].u, actor.mapcoord[actor.polygon.b].v );
glVertex3f ( actor.vertex[actor.polygon.b].x, actor.vertex[actor.polygon.b].y, actor.vertex[actor.polygon.b].z );
// draw third vertex
glTexCoord2f ( actor.mapcoord[actor.polygon.c].u, actor.mapcoord[actor.polygon.c].v );
glVertex3f ( actor.vertex[actor.polygon.c].x, actor.vertex[actor.polygon.c].y, actor.vertex[actor.polygon.c].z );
// done drawing polygon
glEnd ( );
}
// pop the matrix
glPopMatrix ( );
// disable sphere mapping
glDisable ( GL_TEXTURE_GEN_S );
glDisable ( GL_TEXTURE_GEN_T );
}
My light class definitions ( that I used in the initialization code above )...
void light::init ( float ambient[], float diffuse[], float specular[] )
// initializes a light
{
glLightfv ( GL_LIGHT1, GL_AMBIENT, ambient );
glLightfv ( GL_LIGHT1, GL_DIFFUSE, diffuse );
glLightfv ( GL_LIGHT1, GL_SPECULAR, specular );
glLightModeli ( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
glEnable ( GL_LIGHT1 );
}
void light::toggle ( void )
// toggles a light on or off
{
if ( mode == true )
// if light is activated
{
glDisable ( GL_LIGHT1 );
mode = false;
}
else
// if light is deactivated
{
glEnable ( GL_LIGHT1 );
mode = true;
}
}
void light::toggle ( bool new_mode )
// switch a light to a specific state
{
mode = new_mode;
if ( mode == true )
// if light is activated
glEnable ( GL_LIGHT1 );
else
// if light is activated
glDisable ( GL_LIGHT1 );
}
void light::set_position ( float light_position[] )
// updates the position of the light
{
// reset the matrix
glLoadIdentity ( );
// position the camera
cam.update ( );
// move the light
glLightfv ( GL_LIGHT1, GL_POSITION, light_position );
}
My normal calculations ( should be correct though )...
void cross_product ( float *c,float a[3], float b[3] )
// finds the cross product of two vectors
{
c[0] = a[1] * b[2] - b[1] * a[2];
c[1] = a[2] * b[0] - b[2] * a[0];
c[2] = a[0] * b[1] - b[0] * a[1];
}
void normalize ( float * vect )
// scales a vector to a length of 1
{
float length;
int a;
length = ( float ) sqrt ( pow ( vect[0], 2 ) + pow ( vect[1], 2 ) + pow ( vect[2], 2 ) );
for ( a = 0; a < 3; ++a )
// divides vector by its length to normalize
{
vect[a] /= length;
}
}
void get_face_normal ( float *norm, float pointa[3], float pointb[3], float pointc[3] )
// gets the normal of a face
{
float vect[2][3];
int a,b;
float point[3][3];
for ( a = 0; a < 3; ++a )
// copies points into point[][]
{
point[0][a]=pointa[a];
point[1][a]=pointb[a];
point[2][a]=pointc[a];
}
for ( a = 0; a < 2; ++a )
// calculates vectors from point[0] to point[1]
{
for ( b = 0; b < 3; ++b )
// and point[0] to point[2]
{
vect[a] = point[2-a] - point[0];
}
}
// calculates vector at 90° to to 2 vectors
cross_product ( norm, vect[0], vect[1] );
// makes the vector length 1
normalize ( norm );
}
Can anybody help me? What is wrong?
[Edited by - d h k on October 8, 2005 9:01:30 AM]