Often you will have 3D polygonal data for an object, but need to generate normal vectors for it, in order to light it.
To compute normals from polygonal vertex data, use the cross product.
The cross product is a function of two vectors that will produce a new vector that is perpendicular to the other two. If the two vectors are edges of a polygon, then the cross product will give you a normal vector for the polygon (you will need to normalize its length to be 1.0, however).
The formula for the cross product of two vectors A & B is:
[ ( Ay Bz - Az By ), ( Az Bx - Ax Bz ), ( Ax By - Ay Bx ) ]
The Python equivalent for the cross product is:
def crossProduct(A,B):
return [ A[1] * B[2] - A[2] * B[1],
A[2] * B[0] - A[0] * B[2],
A[0] * B[1] - A[1] * B[0] ]
The direction of the cross product is determined by the right-hand rule applied from vector A to vector B (so if you multiply them in the reverse order, the result will point the opposite direction).
Given the vertex data for a polygon, you can compute a normal to the polygon by taking two non-collinear edges (we usually just assume that no two adjacent edges will be collinear), compute the cross product, and normalize the result.
The following function can be used, passing it the first three vertices of your polygon:
# computeNormal - takes 3 vertex positions as input (v0, v1, v2), and
# returns a unit length normal vector for the polygon (normal)
def computeNormal(v0,v1,v2):
A = [ v2[0] - v1[0],
v2[1] - v1[1],
v2[2] - v1[2] ]
B = [ v0[0] - v1[0],
v0[1] - v1[1],
v0[2] - v1[2] ]
product = [ A[1] * B[2] - A[2] * B[1],
A[2] * B[0] - A[0] * B[2],
A[0] * B[1] - A[1] * B[0] ]
length = math.sqrt(product[0]*product[0] +
product[1]*product[1] +
product[2]*product[2])
if (length == 0): # If there's a problem,
return [0, 1, 0] # return an arbitrary result
else:
return [ product[0]/length,
product[1]/length,
product[2]/length ]