Calculating Normals

hi, i’m currently working on my first opengl project and am trying to implement some lighting. Every site I go to tells me I need to calculate normals for my object. Can anyone tell me what normals are and how to calculate them. What would be the normals for the following cube?

glBegin(GL_QUADS);


	glVertex3f( 0.2f, 0.2f,-0.2f);			// Top Right Of The Quad (Top)
	glVertex3f(-0.2f, 0.2f,-0.2f);			// Top Left Of The Quad (Top)
	glVertex3f(-0.2f, 0.2f, 0.2f);			// Bottom Left Of The Quad (Top)
	glVertex3f( 0.2f, 0.2f, 0.2f);			// Bottom Right Of The Quad (Top)

	glVertex3f( 0.2f,-0.2f, 0.2f);			// Top Right Of The Quad (Bottom)
	glVertex3f(-0.2f,-0.2f, 0.2f);			// Top Left Of The Quad (Bottom)
	glVertex3f(-0.2f,-0.2f,-0.2f);			// Bottom Left Of The Quad (Bottom)
	glVertex3f( 0.2f,-0.2f,-0.2f);			// Bottom Right Of The Quad (Bottom)

	glVertex3f( 0.2f, 0.2f, 0.2f);			// Top Right Of The Quad (Front)
	glVertex3f(-0.2f, 0.2f, 0.2f);			// Top Left Of The Quad (Front)
	glVertex3f(-0.2f,-0.2f, 0.2f);			// Bottom Left Of The Quad (Front)
	glVertex3f( 0.2f,-0.2f, 0.2f);			// Bottom Right Of The Quad (Front)

	glVertex3f( 0.2f,-0.2f,-0.2f);			// Bottom Left Of The Quad (Back)
	glVertex3f(-0.2f,-0.2f,-0.2f);			// Bottom Right Of The Quad (Back)
	glVertex3f(-0.2f, 0.2f,-0.2f);			// Top Right Of The Quad (Back)
	glVertex3f( 0.2f, 0.2f,-0.2f);			// Top Left Of The Quad (Back)

	glVertex3f(-0.2f, 0.2f, 0.2f);			// Top Right Of The Quad (Left)
	glVertex3f(-0.2f, 0.2f,-0.2f);			// Top Left Of The Quad (Left)
	glVertex3f(-0.2f,-0.2f,-0.2f);			// Bottom Left Of The Quad (Left)
	glVertex3f(-0.2f,-0.2f, 0.2f);			// Bottom Right Of The Quad (Left)

	glVertex3f( 0.2f, 0.2f,-0.2f);			// Top Right Of The Quad (Right)
	glVertex3f( 0.2f, 0.2f, 0.2f);			// Top Left Of The Quad (Right)
	glVertex3f( 0.2f,-0.2f, 0.2f);			// Bottom Left Of The Quad (Right)
	glVertex3f( 0.2f,-0.2f,-0.2f);			// Bottom Right Of The Quad (Right)

glEnd();

Really would appreciate some sort of guidance abou this.

A normal to a plane is a vector (or direction) which is perpendicular to the plane. The way to calculate is to use a vector cross product.

Say your coordinates are
x1,y1,z1
x2,y2,z2
x3,y3,z3
x4,y4,z4

Then you can specify a vector which has components

(x2-x1), (y2-y1), (z2-z1)

The other vector can be specified as

(x4-x1), (y4-y1), (z4-z1)

Then the components of the normal vector can be calculated from

(y2-y1)(z4-z1)-(z2-z1)(y4-y1)
-(x2-x1)(z4-z1)+(z2-z1)(x4-x1)
(x2-x1)(y4-y1)-(y2-y1)(x4-x1)

You need to normalise the above components. Refer to any maths book with vector algebra.

Hope this helps

Originally posted by jb:
[b]hi, i’m currently working on my first opengl project and am trying to implement some lighting. Every site I go to tells me I need to calculate normals for my object. Can anyone tell me what normals are and how to calculate them. What would be the normals for the following cube?

glBegin(GL_QUADS);

  glVertex3f( 0.2f, 0.2f,-0.2f);			// Top Right Of The Quad (Top)
  glVertex3f(-0.2f, 0.2f,-0.2f);			// Top Left Of The Quad (Top)
  glVertex3f(-0.2f, 0.2f, 0.2f);			// Bottom Left Of The Quad (Top)
  glVertex3f( 0.2f, 0.2f, 0.2f);			// Bottom Right Of The Quad (Top)
  glVertex3f( 0.2f,-0.2f, 0.2f);			// Top Right Of The Quad (Bottom)
  glVertex3f(-0.2f,-0.2f, 0.2f);			// Top Left Of The Quad (Bottom)
  glVertex3f(-0.2f,-0.2f,-0.2f);			// Bottom Left Of The Quad (Bottom)
  glVertex3f( 0.2f,-0.2f,-0.2f);			// Bottom Right Of The Quad (Bottom)
  glVertex3f( 0.2f, 0.2f, 0.2f);			// Top Right Of The Quad (Front)
  glVertex3f(-0.2f, 0.2f, 0.2f);			// Top Left Of The Quad (Front)
  glVertex3f(-0.2f,-0.2f, 0.2f);			// Bottom Left Of The Quad (Front)
  glVertex3f( 0.2f,-0.2f, 0.2f);			// Bottom Right Of The Quad (Front)
  glVertex3f( 0.2f,-0.2f,-0.2f);			// Bottom Left Of The Quad (Back)
  glVertex3f(-0.2f,-0.2f,-0.2f);			// Bottom Right Of The Quad (Back)
  glVertex3f(-0.2f, 0.2f,-0.2f);			// Top Right Of The Quad (Back)
  glVertex3f( 0.2f, 0.2f,-0.2f);			// Top Left Of The Quad (Back)
  glVertex3f(-0.2f, 0.2f, 0.2f);			// Top Right Of The Quad (Left)
  glVertex3f(-0.2f, 0.2f,-0.2f);			// Top Left Of The Quad (Left)
  glVertex3f(-0.2f,-0.2f,-0.2f);			// Bottom Left Of The Quad (Left)
  glVertex3f(-0.2f,-0.2f, 0.2f);			// Bottom Right Of The Quad (Left)
  glVertex3f( 0.2f, 0.2f,-0.2f);			// Top Right Of The Quad (Right)
  glVertex3f( 0.2f, 0.2f, 0.2f);			// Top Left Of The Quad (Right)
  glVertex3f( 0.2f,-0.2f, 0.2f);			// Bottom Left Of The Quad (Right)
  glVertex3f( 0.2f,-0.2f,-0.2f);			// Bottom Right Of The Quad (Right)

glEnd();

Really would appreciate some sort of guidance abou this.[/b]

normals are vectors which are perpendicular to the surface and have unit length
most easy way to calculate them is to make use of the cross-product and normalize the resulting vector (if you do not know what this means you should take a look at the basics of vector math)

i did not look at your code but when you use standard alignment your normal for the top face would be (0,1,0) which is perpendicular to the x-z plane
for the bottom it would be (0,-1,0) because you want it to point in the opposite direction of your top face normal
you should be able to ‘calculate’ the normals for your other faces easily

you specify them using glnormal
for your example it is enough to specify only 1 normal for each surface

hope it helps

[This message has been edited by satan (edited 02-16-2002).]

Simple, to get a normal, you simply need a perpendicular line which is perpendicular to two other lines, which can be say two sides of a triangle. Just take the cross product of two sides of a triangle to get the normal. Then youd have to normalise the resulting vector dont forget. I forget th formula for cross product but its easy to find.

It is important to understand that each vertex has a normal. There is a very good reason for this. The value of a vertex’s normal is not set to the normal of the poly, it is set to the normal of the surface being represented by the mesh. That (and Gouraud shading) is what makes a mesh look smooth when it is lit.

In the case of a cube, the edges and corners are sharp, so each corner has multiple normals (one for each face). In OpenGL, you are limited to one normal per vertex and you are forced to use multiple vertices (one for each normal) for each corner. That’s why it takes 24 vertices to draw a cube instead of 8.

If you are unable to compute the normal of the surface at a vertex, you can do the next best thing – average the normals of all faces that share the vertex (sharp edges and corners are more complicated). 3D programs generally give you the normals so you don’t have to calculate them yourself.

Originally posted by Jambolo:
[b]In the case of a cube, the edges and corners are sharp, so each corner has multiple normals (one for each face). In OpenGL, you are limited to one normal per vertex and you are forced to use multiple vertices (one for each normal) for each corner. That’s why it takes 24 vertices to draw a cube instead of 8.

If you are unable to compute the normal of the surface at a vertex, you can do the next best thing – average the normals of all faces that share the vertex (sharp edges and corners are more complicated). 3D programs generally give you the normals so you don’t have to calculate them yourself.[/b]

I thought for sharp surfaces you would use the normal for the poly, instead of some conjunction of vertex normals. So for a cube you would specify 6 normals (1 for each face) which would be much faster and less tedious. In that case sharp edges and corners should be simpler.

If you are using vertex arrays, you have to specify a normal per vertex, hence for the cube you do end up with 24 vertices and 24 normals (at a minimum).

Originally posted by Furrage:
I thought for sharp surfaces you would use the normal for the poly, instead of some conjunction of vertex normals. So for a cube you would specify 6 normals (1 for each face) which would be much faster and less tedious. In that case sharp edges and corners should be simpler.

You don’t always use the normal of the poly for sharp edges. In the cases of a curved knife blade or the rim of a can (for example), you would average the normals, but exclude the adjacent polys across the sharp edge.

Thank you Defry for clarifying – I was thinking vertex arrays when I said 1 normal per vertex.

And thank you Furrage for clarifying – not using vertex arrays would require specifying normals only 6 times for a cube.