ClawMarkZ

12-02-2008, 07:39 AM

Hi, I'm studying openGL for university second year and I am having some problems with light and textures on a sphere.

The code to make the sphere was given to us by our tutor and I came up with the function to calculate normals:

Sphere funtion:

void drawSphere(float r, int n)

{

float len=r;

int inc=n;

int z,x;

float pi = M_PI;

for(z=0;z<90;z+=inc)

{

float dist1=len*sin((pi*z)/180);

float dist2=len*sin((pi*(z+inc))/180);

float dist1a=sqrt(len*len-dist1*dist1);

float dist2a=sqrt(len*len-dist2*dist2);

#if(1)

for(x=0;x<360;x+=inc)

{

float x1=dist1a*cos((2 *pi*x)/360);

float y1=dist1a*sin(2 *pi*x/360);

float x2=dist1a*cos(2 *pi*(x+inc)/360);

float y2=dist1a*sin(2 *pi*(x+inc)/360);

float x3=dist2a*cos(2 *pi*x/360);

float y3=dist2a*sin(2 *pi*x/360);

float x4=dist2a*cos(2 *pi*(x+inc)/360);

float y4=dist2a*sin(2 *pi*(x+inc)/360);

stVec p1,p2,p3;

p1.x= x1; p1.y=y1; p1.z= dist1;

p2.x= x2; p2.y=y2; p2.z= dist1;

p3.x= x4; p3.y=y4; p3.z=dist2;

CalcNormal(p2.x, p2.y, p2.z, p1.x, p1.y, p1.z, p3.x, p3.y, p3.z);

//printf("X: %f Y: %f Z: %f \n",normal.x,normal.y,normal.z);

glNormal3f(normal.x,normal.y,normal.z);

glBegin(GL_QUADS);

glTexCoord2f(0.0, 0.0); glVertex3f(x1,y1,dist1);

glTexCoord2f(0.0, 1.0); glVertex3f(x2,y2,dist1);

glTexCoord2f(1.0, 1.0); glVertex3f(x4,y4,dist2);

glTexCoord2f(1.0, 0.0); glVertex3f(x3,y3,dist2);

glEnd();

p1.x= x1; p1.y=y1; p1.z= -dist1;

p2.x= x2; p2.y=y2; p2.z= -dist1;

p3.x= x4; p3.y=y4; p3.z= -dist2;

CalcNormal(p2.x, p2.y, p2.z, p1.x, p1.y, p1.z, p3.x, p3.y, p3.z);

glNormal3f(normal .x,normal.y,normal.z);

glBegin(GL_QUADS);

glTexCoord2f(0.0, 0.0); glVertex3f(x1,y1,-dist1);

glTexCoord2f(0.0, 1.0); glVertex3f(x2,y2,-dist1);

glTexCoord2f(1.0, 1.0); glVertex3f(x4,y4,-dist2);

glTexCoord2f(1.0, 0.0); glVertex3f(x3,y3,-dist2);

glEnd();

}

#endif

}

}

Normals function:

void CalcNormal(float p1_x,float p1_y,float p1_z,float p2_x,float p2_y,float p2_z,float p3_x,float p3_y,float p3_z)

{

// Calculate vectors

float var1_x = p2_x - p1_x;

float var1_y = p2_y - p1_y;

float var1_z = p2_z - p1_z;

float var2_x = p3_x - p1_x;

float var2_y = p3_y - p1_y;

float var2_z = p3_z - p1_z;

// Get cross product of vectors

normal.x = (var1_y * var2_z) - (var2_y * var1_z);

normal.y = (var1_z * var2_x) - (var2_z * var1_x);

normal.z = (var1_x * var2_y) - (var2_x * var1_y);

// Normalise final vector

float vLen = sqrt( (normal.x * normal.x) + (normal.y * normal.y) + (normal.z * normal.z) );

normal.x = normal.x/vLen;

normal.y = normal.y/vLen;

normal.z = normal.z/vLen;

}

These dont seem to be working very well... Using the sphere function to draw a textured sphere works ok, except all sides have a default normal of [0, 0, 1]; so light looks flat, when I implement the CalcNormal function to get the normal of each face on the sphere they seem to be completely wrong.

Each square is lit completely wrong, one may be very dark the next might be very bright, there is no coherence between faces.

Is there anything obvious I'm doing wrong? Ive only been using openGL for a few weeks so I'm a complete noob.

Thanks for any help :)

The code to make the sphere was given to us by our tutor and I came up with the function to calculate normals:

Sphere funtion:

void drawSphere(float r, int n)

{

float len=r;

int inc=n;

int z,x;

float pi = M_PI;

for(z=0;z<90;z+=inc)

{

float dist1=len*sin((pi*z)/180);

float dist2=len*sin((pi*(z+inc))/180);

float dist1a=sqrt(len*len-dist1*dist1);

float dist2a=sqrt(len*len-dist2*dist2);

#if(1)

for(x=0;x<360;x+=inc)

{

float x1=dist1a*cos((2 *pi*x)/360);

float y1=dist1a*sin(2 *pi*x/360);

float x2=dist1a*cos(2 *pi*(x+inc)/360);

float y2=dist1a*sin(2 *pi*(x+inc)/360);

float x3=dist2a*cos(2 *pi*x/360);

float y3=dist2a*sin(2 *pi*x/360);

float x4=dist2a*cos(2 *pi*(x+inc)/360);

float y4=dist2a*sin(2 *pi*(x+inc)/360);

stVec p1,p2,p3;

p1.x= x1; p1.y=y1; p1.z= dist1;

p2.x= x2; p2.y=y2; p2.z= dist1;

p3.x= x4; p3.y=y4; p3.z=dist2;

CalcNormal(p2.x, p2.y, p2.z, p1.x, p1.y, p1.z, p3.x, p3.y, p3.z);

//printf("X: %f Y: %f Z: %f \n",normal.x,normal.y,normal.z);

glNormal3f(normal.x,normal.y,normal.z);

glBegin(GL_QUADS);

glTexCoord2f(0.0, 0.0); glVertex3f(x1,y1,dist1);

glTexCoord2f(0.0, 1.0); glVertex3f(x2,y2,dist1);

glTexCoord2f(1.0, 1.0); glVertex3f(x4,y4,dist2);

glTexCoord2f(1.0, 0.0); glVertex3f(x3,y3,dist2);

glEnd();

p1.x= x1; p1.y=y1; p1.z= -dist1;

p2.x= x2; p2.y=y2; p2.z= -dist1;

p3.x= x4; p3.y=y4; p3.z= -dist2;

CalcNormal(p2.x, p2.y, p2.z, p1.x, p1.y, p1.z, p3.x, p3.y, p3.z);

glNormal3f(normal .x,normal.y,normal.z);

glBegin(GL_QUADS);

glTexCoord2f(0.0, 0.0); glVertex3f(x1,y1,-dist1);

glTexCoord2f(0.0, 1.0); glVertex3f(x2,y2,-dist1);

glTexCoord2f(1.0, 1.0); glVertex3f(x4,y4,-dist2);

glTexCoord2f(1.0, 0.0); glVertex3f(x3,y3,-dist2);

glEnd();

}

#endif

}

}

Normals function:

void CalcNormal(float p1_x,float p1_y,float p1_z,float p2_x,float p2_y,float p2_z,float p3_x,float p3_y,float p3_z)

{

// Calculate vectors

float var1_x = p2_x - p1_x;

float var1_y = p2_y - p1_y;

float var1_z = p2_z - p1_z;

float var2_x = p3_x - p1_x;

float var2_y = p3_y - p1_y;

float var2_z = p3_z - p1_z;

// Get cross product of vectors

normal.x = (var1_y * var2_z) - (var2_y * var1_z);

normal.y = (var1_z * var2_x) - (var2_z * var1_x);

normal.z = (var1_x * var2_y) - (var2_x * var1_y);

// Normalise final vector

float vLen = sqrt( (normal.x * normal.x) + (normal.y * normal.y) + (normal.z * normal.z) );

normal.x = normal.x/vLen;

normal.y = normal.y/vLen;

normal.z = normal.z/vLen;

}

These dont seem to be working very well... Using the sphere function to draw a textured sphere works ok, except all sides have a default normal of [0, 0, 1]; so light looks flat, when I implement the CalcNormal function to get the normal of each face on the sphere they seem to be completely wrong.

Each square is lit completely wrong, one may be very dark the next might be very bright, there is no coherence between faces.

Is there anything obvious I'm doing wrong? Ive only been using openGL for a few weeks so I'm a complete noob.

Thanks for any help :)