05.23.10
3d vector graphics using canvas - back face culling
The previous post shows how to display a wireframe model using canvas and javascript. One problem with the example is that the spaceship appears to be transparent. This is because we’re drawing all the faces that make up the shape, instead of just the faces that are pointing towards the viewer.
We decide which faces are pointing towards the viewer using a vector cross-product. The cross-product of 2 3-dimensional vectors is another vector whose direction is at right-angles to the first 2. So the cross-product of 2 vectors along a face points directly away from the face. If the cross-product vector has a negative Z-component, it is pointing towards the viewer (we define the positive direction of the Z axis as pointing into the screen) and thus we should be able to see the face.
The good news is that we’re only interested in the Z component of the cross-product, which simplifies matters considerably. Given a list of points (p0, p1, p2, ….) that define a face, we create 2 vectors A = p0 - p1 and B = p2 - p1. If the components of A and B are (ax, ay, az) and (bx, by, bz) then the Z component of A x B is
(A x B)z = ax * by - bx * ay
Substituting p0 etc. back into the equation above, we get
z_component =
(p2[0] - p1[0]) * (p0[1] - p1[1]) - (p0[0] - p1[0]) * (p2[1] - p1[1])
This technique works well for convex shapes. A shape is said to be convex if a straight line can be drawn between any 2 points inside the shape without the line ever crossing the boundary of the shape. Because of this, I commented out the gun/antenna part of the ship - the remaining part of the ship is convex. Have a look at the results here.
There is still 1 important thing missing - perspective. At the moment, the ship is the same size no matter how far away from the viewer it is. We’ll have a look at this next time.