Reputation: 272
I am having difficulty figuring out how to calculate normal, I think I have some misunderstandings so I would like to give an example of a piece of simple geometry and figure out the normal in which case it should be a little clearer how to do it with harder geometry.
glBegin(GL_QUADS);
glVertex3f(1,1,-1);
glVertex3f(1,1,1);
glVertex3f(-1,1,1);
glVertex3f(-1,1,-1);
glEnd();
At every vertex I know I need to put in a normal value (I want to light this) so this represents a front facing square (2 x 2). So before every vertex would I have a normal of (0, 1.0, 0)?
Upvotes: 1
Views: 5060
Reputation: 26157
When you need to calculate the normal of a quad you need to calculate the cross-product of your quad's 4 vertices.
A = (1, 1, -1)
B = (1, 1, 1)
C = (-1, 1, 1)
D = (-1, 1, -1)
This is how your quads vertices are laid out. The reason I'm adding this, is because the order you calculate the following vertices in, is important!
A----B
| |
| |
D----C
So now when you want to calculate the normal, you simply need to do.
normal = (C - A) x (D - B)
Where x means cross-product.
In case you don't know what a cross-product is or how to calculate it, then here I will show you how to calculate it.
V1 = (C - A)
V2 = (D - B)
Then we calculate the cross-product by doing the following.
normal.x = V1.y * V2.z - V1.z * V2.y
normal.y = V2.x * V1.z - V2.z * V1.x
normal.z = V1.x * V2.y - V1.y * V2.x
Where the above 3 lines is the equivalent of writing.
normal = V1 x V2
Now we've calculated the cross-product, which in this case is a 3D Vector.
If you didn't know what a cross-product is, and want to read more about it, then you can read more about it on these two links.
I did the cross product, it is normal = (0, 8, 0), if I normalize it I get (0, 1, 0)
Just to clarify something for you, the reason we need to normalize the normal, is because we're calculating the normal distribution of x, y, z,
between 0 <-> 1
If you want to normalize a vector you would do the following.
length = sqrt(x * x + y * y + z * z)
if (length > 0) {
x /= length
y /= length
z /= length
}
Also if you want to check if you need to normalize a vector or not, you can do the following.
if ((x * x + y * y + z * z) != 1) {
// NORMALIZE THE VECTOR
}
Now does that mean I only need to put it once over the vertices or do I need to mention it for every vertex in the quad.
First Way
glBegin(GL_QUADS);
glNormal3f(0, 1, 0);
glVertex3f(1, 1, -1);
glVertex3f(1, 1, 1);
glVertex3f(-1, 1, 1);
glVertex3f(-1, 1, -1);
glEnd();
Second Way
glBegin(GL_QUADS);
glNormal3f(0, 1, 0);
glVertex3f(1, 1, -1);
glNormal3f(0, 1, 0);
glVertex3f(1, 1, 1);
glNormal3f(0, 1, 0);
glVertex3f(-1, 1, 1);
glNormal3f(0, 1, 0);
glVertex3f(-1, 1, -1);
glEnd();
It doesn't really matter if you do it the first or the second way. As long as your quad is plain, so if it's completely flat you can do either the first or second way.
Though if your quad isn't completely flat, then you need to do the second way, because then each vertex of the quad will/might have a different normal.
Many resources says you need to calculate the normal for every vertex though.
That is true, though as I said above, if you calculating a normal for a completely flat quad, then the normal for each vertex will be the same, therefore you can save some calculation/time/CPU by simply only calculating the normal once and using it for each vertex, as long as possible.
Upvotes: 13