I have been working on some simple XNA proof of concept for a game idea I have as well as just to further my learning in XNA. However, i seem to be stuck on these dreaded normals, and using the BasicEffect with default lighting i can't seem to tell if my normals are being calculated correctly, hence the question.

I'm mainly drawing cubes at the moment, I'm using a triangle list and a VertexBuffer to get the job done. The north face of my cube has two polygons and 6 vectors:

Vector3 startPosition = new Vector3(0,0,0);
corners[0] = startPosition; // This is the start position. Block size is 5.
            corners[1] = new Vector3(startPosition.X, startPosition.Y + BLOCK_SIZE, startPosition.Z);
            corners[2] = new Vector3(startPosition.X + BLOCK_SIZE, startPosition.Y, startPosition.Z);
            corners[3] = new Vector3(startPosition.X + BLOCK_SIZE, startPosition.Y + BLOCK_SIZE, startPosition.Z);

            verts[0] = new VertexPositionNormalTexture(corners[0], normals[0], textCoordBR);
            verts[1] = new VertexPositionNormalTexture(corners[1], normals[0], textCoordTR);
            verts[2] = new VertexPositionNormalTexture(corners[2], normals[0], textCoordBL);
            verts[3] = new VertexPositionNormalTexture(corners[3], normals[0], textCoordTL);
            verts[4] = new VertexPositionNormalTexture(corners[2], normals[0], textCoordBL);
            verts[5] = new VertexPositionNormalTexture(corners[1], normals[0], textCoordTR);

Using those coordinates I want to generate the normal for the north face, I have no clue how to get the average of all those vectors and create a normal for the two polygons that it makes.

Here is what i tried:

            normals[0] = Vector3.Cross(corners[1], corners[2]);

It seems like its correct, but then using the same thing for other sides of the cube the lighting effect seems weird, and not cohesive with where i think the light source is coming from, not really sure with the BasicEffect.

Am I doing this right? Can anyone explain in lay mans terms how normals are calculated. Any help is much appreciated.

Note: I tried going through Riemers and such to figure it out with no luck, it seems no one really goes over the math well enough. Thanks!


2 Answers 2


Normals for flat faces (like the side of a cube) are at right angles to the triangles themselves. To work out what these should be you can either calculate them using the cross product like you are (though you will want to take the cross product of (vert[1] - vert[0]) X (vert[2] - vert[0]) - so you're using vectors on the plane not vertices in the plane). Moving to this vert[a] - vert[b] form should fix the weirdness you're experiencing.

However to make things a bit simpler in this case you can just set the normals manually. For this face of the cube the vertices all lie in the plane where Z = 0 (since startPosition.Z = 0 and all faces use startPosition.Z for their Z coordinate), so the normal = (0,0,1).

  • \$\begingroup\$ Thanks a lot, most of the tutorials i saw were using pre-build vector lists so it was hard to tell what math they were actually applying to what vectors, using it in context here helped me understand it easily, i appreciate it! \$\endgroup\$
    – Wade
    Dec 23, 2010 at 21:00
        normals[0] = Vector3.Cross(corners[1], corners[2]);

There is a subtle problem here, the two corner vectors that you are crossing are vectors that go from the origin to the corners. What you want to cross are two edges of the face (vectors that go from one corner to another corner). try:

Vector3 edge1 = corners[1] - corners[0];
Vector3 edge2 = corners[2] - corners[0];
normals[0] = Vector3.Cross(edge1, edge2);

I assumed that corners 0, 1, 2 are all associated with the same face.

This may produce a normal that points in the wrong direction depending on how the corners wind. If you think the normal is pointing inward to the cube instead of outward, simply switch places of the edges in the cross function.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .