Reputation: 5532
I am drawing a sphere using quads. I plot an extra vertex, just to divide the quad into 2 triangles. So it goes like this:
1 ----> 2
| |
| |
4 ----> 3
but after 3 I plot 1 again. So imagine an extra line from 3-->1.
I am now trying to calculate each vertex' normal. Here is my code:
//calculate normals
for (no_vertice=0; no_vertice<12887; no_vertice+=1)
{
//getting the sphere's vertices
x=sphere_vertices[no_vertice].position[0];
y=sphere_vertices[no_vertice].position[1];
z=sphere_vertices[no_vertice].position[2];
//normalising vector "norm(Vertex - Center)"
magnitude = sqrt((x*x) + (y*y) + (z*z));
sphere_vertices[no_vertice].normal[0] = (x/magnitude);
sphere_vertices[no_vertice].normal[1] = (y/magnitude);
sphere_vertices[no_vertice].normal[2] = (z/magnitude);
printf("Normal at vertice %d = X:%f, Y:%f, Z:%f. \n", no_vertice, sphere_vertices[no_vertice].normal[0], sphere_vertices[no_vertice].normal[1], sphere_vertices[no_vertice].normal[2]);
}
I am calculating the magnitude for each vertex, and then dividing each component of that vertex with the magnitude so I get a unit vector. The problem is that I get a lot of zero vectors. that is vertices with x=0, y=0, z=0... When I pass the normal to the vertex shader,
//my vertex structure
struct Vertex {
GLdouble position[3];
GLfloat color[3];
GLdouble normal[3];
};
....
..
.
/* Enable attribute index 2 as being used */
glEnableVertexAttribArray ( 2 );
glVertexAttribPointer ( ( GLuint ) 2, 3, GL_FLOAT, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* )
offsetof(struct Vertex, normal) );
...
..
.
//pass the normal to vertex shader
glBindAttribLocation(shaderprogram, 2, "in_Normal");
and do my light calculation I get all weird kind of effects.
Am I doing anything wrong?
The most confusing part is I am asked to do this:
"For the sphere, work out the surface normal direction and augment your wire-frame drawing with short lines representing the normal direction of each vertex The sphere should now appear to be a hedge hog."
"Note: The surface normal is the unit vector at right angles to the surface patch, assuming it is flat."
So is it basically the normal to a vertex, or to the quad surface that I have to draw? I am confused because it says,
"work out the surface normal direction"
and then
"drawing with short lines representing the normal direction of each vertex"
So where the lines should be drawn??? on the vertex? or in the middle of the quad? Thanks
EDIT: Vertex Calculation
for (theta=-90;theta<=90-dtheta;theta+=dtheta) {
for (phi=0;phi<=360-dphi;phi+=dphi) {
//calculating Vertex 1
x = cos(theta*DTOR) * cos(phi*DTOR);
y = cos(theta*DTOR) * sin(phi*DTOR);
z = sin(theta*DTOR);
no_vertice+=1;
sphere_vertices[no_vertice].position[0] = x;
sphere_vertices[no_vertice].position[1] = y;
sphere_vertices[no_vertice].position[2] = z;
//calculating Vertex 2
x = cos((theta+dtheta)*DTOR) * cos(phi*DTOR);
y = cos((theta+dtheta)*DTOR) * sin(phi*DTOR);
z = sin((theta+dtheta)*DTOR);
no_vertice+=1;
sphere_vertices[no_vertice].position[0] = x;
sphere_vertices[no_vertice].position[1] = y;
sphere_vertices[no_vertice].position[2] = z;
//calculating Vertex 3
x = cos((theta+dtheta)*DTOR) * cos((phi+dphi)*DTOR);
y = cos((theta+dtheta)*DTOR) * sin((phi+dphi)*DTOR);
z = sin((theta+dtheta)*DTOR);
no_vertice+=1;
sphere_vertices[no_vertice].position[0] = x;
sphere_vertices[no_vertice].position[1] = y;
sphere_vertices[no_vertice].position[2] = z;
//adding Vertex_1 again to divide the Quad into 2 triangles
//calculating Vertex 1
x = cos(theta*DTOR) * cos(phi*DTOR);
y = cos(theta*DTOR) * sin(phi*DTOR);
z = sin(theta*DTOR);
no_vertice+=1;
sphere_vertices[no_vertice].position[0] = x;
sphere_vertices[no_vertice].position[1] = y;
sphere_vertices[no_vertice].position[2] = z;
if (theta > -90 && theta < 90) {
//calculating Vertex 4
x = cos(theta*DTOR) * cos((phi+dphi)*DTOR);
y = cos(theta*DTOR) * sin((phi+dphi)*DTOR);
z = sin(theta*DTOR);
no_vertice+=1;
sphere_vertices[no_vertice].position[0] = x;
sphere_vertices[no_vertice].position[1] = y;
sphere_vertices[no_vertice].position[2] = z;
}
}
}
Upvotes: 1
Views: 535
Reputation: 162164
Your problem(s), as I see them is, that you don't really have a grip for what's actually going on. Instead of looking at code from some tutorials, you should get a grip of the mathematical concepts (trying to filter those from code is counterproductive, since code doesn't tell the full story and also may omit or simplify things for a good enough approximation).
First of all you got the order of vertices, well not wrong, but unhappy. OpenGL assumes right handedness in vector calculations (unless you swap one axis at the end of the transformation pipeline). That means, vertices should be counted counterclockwise. You can do it clockwise, but things get much easier the other way round. Next you should start counting with 0, at least if you're in a C like language that addresses arrays by offset index, i.e. first element is at index 0.
3--2
| /|
|/ |
0--1
The normals of a origin centered sphere are something special, since normalized (don't confuse a "normal" with the normal of normal-ized, they're different things!) vertex position vectors are the normal of the vertex in question.
In the general case a normal can be evaluated by taking the cross product of the tangent space of the vertex, i.e. for a triangle the cross product of the edge vectors at a corner. In your quad's case the normal at [0] would be
normalize( ([1]-[0]) × ([2]-[0]) )
for the triangle 0,1,2 and
normalize( ([2]-[0]) × ([3]-[0]) )
Notice, that this is the cross product of the partial derivatives of the analytical representation of the surface. You already know the analytical representation of a sphere's surface (see Paul Bourke's tutorial). I recommend as an exercise to test this, i.e. proof that for a unit radius sphere around the origin, the position of a point of the surface equals the surface's normal at that point.
Upvotes: 2
Reputation: 7205
It looks like what you are supposed to draw is a sphere made up of squares, imagine an orange with a bunch of squares painted onto it.
Since he wants the vertex normals, each quad will have four normals drawn at each of its vertices, with each normal perpendicular to the quads surface
Note that each vertex would have four different vertex normals, since each vertex is shared by four quads.
edit: In the context of lighting, he probably wants a single normal for each vertex, so just take the average. This is probably what he means, but its not what the instructions say.
Upvotes: 0
Reputation: 473302
At the risk of repeating myself:
For a given vector position P on the sphere who's center is C, the normal is norm(P - C), where norm normalizes the vector.
I don't see your code doing this. Unless you know that the positions are centered on the origin, which is not an assumption you have stated.
Upvotes: 0