Given the code below. Taken from http://pastie.org/pastes/764327/text
void CreateSphere(int PointRows, int PointsPerRow)
{
NumVertices = (PointRows-2)*PointsPerRow + 2;
Vertices = new SVertex[NumVertices];
IndexVect.clear(); //to be sure it is empty
float x,y,z;
int i,j;
double r;
for (i = 1; i < (PointRows-1); i++)
{
for (j = 0; j < PointsPerRow; j++)
{
y = 1.0 - float(i) / float(PointRows-1)*2.0;
r = sin (acos(y)); //radius of the row
x = r * sin(float(j) / float(PointsPerRow)*PI*2.0);
z = r * cos(float(j) / float(PointsPerRow)*PI*2.0);
Vertices[(i-1)*PointsPerRow+j].x = x;
Vertices[(i-1)*PointsPerRow+j].y = y;
Vertices[(i-1)*PointsPerRow+j].z = z;
Vertices[(i-1)*PointsPerRow+j].r = (float)(i) / float(PointRows);
Vertices[(i-1)*PointsPerRow+j].g = 0.7;
Vertices[(i-1)*PointsPerRow+j].b = (float)(j) / float(PointsPerRow);
}
}
//The highest and deepest vertices:
Vertices[(PointRows-2)*PointsPerRow].x = 0.0;
Vertices[(PointRows-2)*PointsPerRow].y = 1.0;
Vertices[(PointRows-2)*PointsPerRow].z = 0.0;
Vertices[(PointRows-2)*PointsPerRow].r = 1.0;
Vertices[(PointRows-2)*PointsPerRow].g = 0.7;
Vertices[(PointRows-2)*PointsPerRow].b = 1.0;
Vertices[(PointRows-2)*PointsPerRow+1].x = 0.0;
Vertices[(PointRows-2)*PointsPerRow+1].y = -1.0;
Vertices[(PointRows-2)*PointsPerRow+1].z = 0.0;
Vertices[(PointRows-2)*PointsPerRow+1].r = 1.0;
Vertices[(PointRows-2)*PointsPerRow+1].g = 0.7;
Vertices[(PointRows-2)*PointsPerRow+1].b = 1.0;
for (i = 1; i < (PointRows-2); i++)
{
for (j = 0; j < (PointsPerRow-1); j++)
{
IndexVect.push_back((i-1)*PointsPerRow+j);
IndexVect.push_back((i-1)*PointsPerRow+j+1);
IndexVect.push_back((i)*PointsPerRow+j);
IndexVect.push_back((i-1)*PointsPerRow+j+1);
IndexVect.push_back((i)*PointsPerRow+j+1);
IndexVect.push_back((i)*PointsPerRow+j);
}
IndexVect.push_back((i-1)*PointsPerRow+PointsPerRow-1);
IndexVect.push_back((i-1)*PointsPerRow);
IndexVect.push_back((i)*PointsPerRow+j);
IndexVect.push_back((i)*PointsPerRow);
IndexVect.push_back((i-1)*PointsPerRow);
IndexVect.push_back((i)*PointsPerRow+j);
}
//The triangles to the highest and deepest vertices:
for (j = 0; j< (PointsPerRow-1); j++)
{
IndexVect.push_back(j);
IndexVect.push_back(j+1);
IndexVect.push_back((PointRows-2)*PointsPerRow);
}
IndexVect.push_back(j);
IndexVect.push_back(0);
IndexVect.push_back((PointRows-2)*PointsPerRow);
for (j = 0; j< (PointsPerRow-1); j++)
{
IndexVect.push_back((PointRows-3)*PointsPerRow+j);
IndexVect.push_back((PointRows-3)*PointsPerRow+j+1);
IndexVect.push_back((PointRows-2)*PointsPerRow+1);
}
IndexVect.push_back((PointRows-3)*PointsPerRow+j);
IndexVect.push_back((PointRows-3)*PointsPerRow);
IndexVect.push_back((PointRows-2)*PointsPerRow+1);
Indices = new GLuint[IndexVect.size()]; //allocate the required memory
for (i = 0; i < IndexVect.size(); i++)
{
Indices[i] = IndexVect[i];
}
NumIndices = IndexVect.size();
IndexVect.clear(); //no longer needed, takes only memory
}
How would you calculate the normals using the resultant Vertices….?
I would then hope to use glEnableClientState(GL_NORMAL_ARRAY) , and glNormalPointer(GL_FLOAT,0, Normals) , along with glDrawElements to draw the resultant indices together with the normals.
I’ve had a go but it just looks wrong. The lighting appears to the left of the sphere, rather than below.
Apologies. I’ve not given the full picture here. Basically I’m trying to generate a random shape, by entering noise into the data.
If I use the following code at the end of the first nested loop:
Normals[(i-1)*PointsPerRow+j].x = x;
Normals[(i-1)*PointsPerRow+j].y = y;
Normals[(i-1)*PointsPerRow+j].z = z;
I am able to generate the correct normals for the sphere and it all looks fine.
However if I do this:
x=x+(noise3(x,y,z));
y=y+(noise3(x,y,z));
z=z+(noise3(x,y,z));
And then try to use:
Normals[(i-1)*PointsPerRow+j].x = x;
Normals[(i-1)*PointsPerRow+j].y = y;
Normals[(i-1)*PointsPerRow+j].z = z;
The normals look wrong for some faces. I want to loop through the resultant indices once the full shape has been created and then calculate the normal for each point, if that makes any sense….?
OK, here is what I got. It does not appear to work.It’s probably completely wrong so go easy.
for (j = 0; j < NumIndices-2; j=j+3)
{
Ax = Vertices[Indices[j]].x; Bx = Vertices[Indices[j+1]].x; Cx = Vertices[Indices[j+2]].x;
Ay = Vertices[Indices[j]].y; By = Vertices[Indices[j+1]].y; Cy = Vertices[Indices[j+2]].y;
Az = Vertices[Indices[j]].z; Bz = Vertices[Indices[j+1]].z; Cz = Vertices[Indices[j+2]].z;
dms::Vector3 p1(Ax,Ay,Az);
dms::Vector3 p2(Bx,By,Bz);
dms::Vector3 p3(Cx,Cy,Cz);
dms::Vector3 V1= (p2 - p1);
dms::Vector3 V2 = (p3 - p1);
dms::Vector3 normal = V1.cross(V2);
Normals[j].x = normal[0];
Normals[j].y = normal[1];
Normals[j].z = normal[2];;
Normals[j+1].x = normal[0];
Normals[j+1].y = normal[1];
Normals[j+1].z = normal[2];;
Normals[j+2].x = normal[0];
Normals[j+2].y = normal[1];
Normals[j+2].z = normal[2];;
}
Edit —
I was able to get a much better result by re-arranging the section where the 2 vectors are calculated. I changed the following:
dms::Vector3 V1= (p2 - p1);
dms::Vector3 V2 = (p3 - p1);
To:
dms::Vector3 V1= (p2 - p1);
dms::Vector3 V2 = (p1 - p3);
It still doesn’t look quite right however, there is dark strip that runs along the front of the sphere, and the top of the sphere looks strange.
Many thanks for Kaganar’s excellent answer which I will work through to resolve my remaining issues. Many thanks also to Bart!
Based on the comments, this is one possible answer:
Regarding the code you’ve posted at the time of writing this answer:
One further note: When you’re normalizing, beware of close-to-zero-length vectors passed to your normalization function, especially if you’re using noisily generated shapes. Since normalization is just dividing the components of the length of a vector, it’s common to check to see if this length is close to zero before doing the division you’d normally expect. If it is close to zero, the output of such a normalize function is typically just the up vector (since a zero vector would cause spuriously dark results in most shading models.)