OpenGL lighting problem

Hello all! I have just started working with OpenGL and I seem to be having some problems regarding lighting and I was hoping someone would be able to help me out. Here’s my situation, I have a diamond with a ball circling it. I need the ball to light the diamond. From what I have done so far, there is light but it doesn’t seem to be coming from the ball. Also, I’m not sure if I’m calculating the normals correctly. Any help or recommendations would be highly appreciated!


#ifdef _WINDOWS
#include <windows.h>
#endif

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

#include "CGfxOpenGL.h"
#include "gmath.h"

// disable float-double conversion warnings
#pragma warning(disable:4305)
#pragma warning(disable:4244)

extern bool Wireframe;

CGfxOpenGL::CGfxOpenGL()
{
}

CGfxOpenGL::~CGfxOpenGL()
{
    Shutdown();
}

bool CGfxOpenGL::Init()
{	
    // erase the background to black
	glClearColor(0.0, 0.0, 0.0, 0.0);

    // initialize a rotation angle
    m_angle = 0.0f;

    // create a quadric object for drawing spheres
    m_Quadric = gluNewQuadric();

    return true;
}

bool CGfxOpenGL::Shutdown()
{
    // delete the quadric object
    if (m_Quadric != NULL) {
        gluDeleteQuadric(m_Quadric);
        m_Quadric = NULL;
    }
	return true;
}

void CGfxOpenGL::SetupProjection(int width, int height)
{
	if (height == 0)					// don't want a divide by zero
	{
		height = 1;					
	}

	glViewport(0, 0, width, height);		// reset the viewport to new dimensions
	glMatrixMode(GL_PROJECTION);			// set projection matrix current matrix
	glLoadIdentity();						// reset projection matrix

	// calculate aspect ratio of window
	gluPerspective(52.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);

	glMatrixMode(GL_MODELVIEW);				// set modelview matrix
	glLoadIdentity();						// reset modelview matrix

	m_windowWidth = width;
	m_windowHeight = height;
}

void CGfxOpenGL::Prepare(float dt)
{
    // update the rotation angle
    m_angle += 0.1f;
}

// draw a normal form the center of poly defined by p1, p2, p3
// using the normal value
// this function used to test/visualize the normal value
void DrawNormal(Vector3& p1, Vector3& p2, Vector3& p3, Vector3& normal) {
    Vector3 center;

    // compute the center of the poly
    center = p1 + p2 + p3;
    center.scale(1.0/3.0);

    // temporarily disable lighting to draw the normal line
    glDisable(GL_LIGHTING);


    // draw a small white line to represent the normal
    glBegin(GL_LINES);
        glColor3f(1.0, 1.0, 1.0);
        glVertex3f(center.x, center.y, center.z);
        glColor3f(1.0, 1.0, 1.0);
        glVertex3f(center.x + normal.x, center.y + normal.y, center.z + normal.z);

    glEnd();

    // re-enable lighting
    glEnable(GL_LIGHTING);
}


// define a single sided face
struct Face {
    int i1, i2, i3;             // indexes into vertex data
};

void CGfxOpenGL::Render()
{
	// enable color tracking
	glEnable(GL_COLOR_MATERIAL);
	// set material properties which will be assigned by glColor
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	// enable lighting
	glEnable(GL_LIGHTING);
    int numFaces = 8;
    Vector3 p1, p2, p3;        // points or vertices of the triangle

    // define 5 vertices of a diamond shape - colors not being used now
    Vector3 vertexes[] = {
        Vector3(  0,  2,  0 ),     // vertex 0
        Vector3(  1,  0,  1 ),     // vertex 1
        Vector3(  1,  0, -1 ),     // vertex 2 ...
        Vector3( -1,  0, -1 ),
        Vector3( -1,  0,  1 ),
        Vector3(  0, -2,  0 )
    };

    // set up the face index data into the vertex array above
    // each triple will define a single face (triangle) of our shape
    Face faceData[] = {
        0, 4, 1,    // top front-facing face
        0, 3, 4,    // top left face
        0, 2, 3,    // top rear face
        0, 1, 2,    // top right face
        5, 1, 4,    // bottom front face ...
        5, 4, 3,
        5, 3, 2, 
        5, 2, 1,
    };

    // clear screen and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
    glLoadIdentity();

	// enable z or depth buffer testing
    glEnable(GL_DEPTH_TEST);

    //if (Wireframe) {
        //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    //}
    //else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    //}


    // move the whole scene back 
    glTranslatef(0.0, 0.0, -10.0f);

    // set up a temporary transform for the orbiting sphere
    glPushMatrix();


        // make light rotate about an odd axis
        glRotatef(m_angle, 1.0f, 1.0f, 0.0f);

        // move the light into upper left corner of the scene
        glTranslatef(-2.0f, 2.0f, 3.0f);
		// setup and enable light
		GLfloat lightPos[] = {0.0f, 0.0f, 1.0f, 1.0f};
		glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
		GLfloat specular[] = {0.0f, 0.0f, 0.0f , 1.0f};
		glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
		GLfloat ambient[] = {1.0f, 1.0f, 1.0f , 1.0f};
		glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, ambient);
		glEnable(GL_LIGHT0);

        // draw a small sphere for light position
        glColor3f(1.0, 1.0, 1.0);
        gluSphere(m_Quadric, 0.2, 10, 10);

    glPopMatrix();

    // rotate object about Y
    glRotatef(m_angle*2, 0.0f, 1.0f, 0.0f);

    // for each of the 8 faces
    for (int i=0; i < numFaces; i++) {
        // draw the faces that make up the diamond shape
		glBegin(GL_TRIANGLES);
			glColor3f(1.0, 0.0, 0.0);
			GLfloat colorRed[] = { 1.0f, 0.0f, 0.0f, 1.0f};
			glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colorRed);
			GLfloat specReflection[] = { 0.8f, 0.8f, 0.8f, 1.0f };
			glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection);
			glMateriali(GL_FRONT, GL_SHININESS, 96);


            // draw 3 vertices with color, light and normal info
            // vertex 1
            p1 = vertexes[faceData[i].i1];
            glVertex3f(p1.x, p1.y, p1.z);
			
            // vertex 2
            p2 = vertexes[faceData[i].i2];
            glVertex3f(p2.x, p2.y, p2.z);

            // vertex 3
            p3 = vertexes[faceData[i].i3];
            glVertex3f(p3.x, p3.y, p3.z);

			// calculate new normal
			Vector3 n1 = p2-p1;
			Vector3 n2 = p3-p1;
			Vector3 newN = CrossProduct(n1,n2);

			// vertex 1
			glNormal3f(newN.x, newN.y, newN.z);
			glVertex3f(p1.x, p1.y, p1.z);

			// vertex 2
			glNormal3f(newN.x, newN.y, newN.z);
			glVertex3f(p2.x, p2.y, p2.z);

			// vertex 3
			glNormal3f(newN.x, newN.y, newN.z);
			glVertex3f(p3.x, p3.y, p3.z);

			vertexes[faceData[i].i1] = p1;
			vertexes[faceData[i].i2] = p2;
			vertexes[faceData[i].i3] = p3;


        glEnd();

    }
}

One potential cause is that your ball (sphere) is centered on 0,0,0 in the local object space, but you position the light source at 0,0,1. Change the latter to 0,0,0.

Also, I’m not sure if I’m calculating the normals correctly.

Are the normals you’re passing to glNormal guarenteed to be unit vectors? If not, normalize them before passing them in. Or glEnable( GL_NORMALIZE ) to ask OpenGL to do it.

See the first tip here:
http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/