In the beginning was the triangle.
Triangles have a lot going for them in 3D graphics. They can be assembled to make almost any type of surface; with proper shading, the surfaces will look smooth and curved. Triangles are compact, requiring very little memory, so many can be used in a scene. They are also very quickly rendered. In addition, as long as the triangle’s three vertices are not collinear (i.e., do not lie along a common line), the triangle defines a unique plane. We never have to worry about triangles deforming into warped, nonplanar forms.
Here’s the threejs code for making the humble triangle that appears above:
function makeTriangle() { let geom = new THREE.Geometry(); let a = new THREE.Vector3(0, 0, 0); let b = new THREE.Vector3(4, 0, 0); let c = new THREE.Vector3(0, 8, 0); geom.vertices.push(a, b, c); let face = new THREE.Face3(0, 1, 2); geom.faces.push(face); let args = {color: 0xFF00FF, side: THREE.DoubleSide}; let mat = new THREE.MeshBasicMaterial(args); let mesh = new THREE.Mesh(geom, mat); return mesh; }
We first build a threejs Geometry
object, followed by three points in space (Vector3
objects). We push these into the array of vertices owned by geom
. Then we build a triangular face on these three vertices, mentioning them by their index in the vertices array (0, 1, and 2), and push this face into our geometry. Lastly we build a material mat
and combine the geometry and material into a mesh
.
The material object mat
is constructed on a JavaScript object {color: 0xFF00FF, side: THREE.DoubleSide}
with two attributes. The color value is a hexadecimal number with six digits. The first two digits refer to the brightness level of red, the next two to green, and the last two to blue. The color specified here is bright in red and blue, which combine to form magenta. The side value, THREE.DoubleSide
says that the triangle can be viewed from its front or from its back. So when we orbit behind it, we can still see it. If it were rendered only from its front side, it would disappear whenever we would orbit to its back side.
A mesh combines a material and a geometry. Meshes are among the main constituents of scenes. Since geometries and materials are constructed independently, each can be reused multiple times. For example, we could build another mesh reusing the same triangle geometry but with a different (say) green material, or we could build another mesh with a different (say) square geometry while reusing same red material. Nonetheless, materials (and appearance generally) and geometry are very often interdependent. This occurs, for example, when a geometry is made up of several elements each of which gets its own appearance. We’ll see a simple example of this in the next page.
There’s a bit of additional code involved in creating this scene of course. But our focus will remain on the code specific to each scene, in this case, the code it takes to produce a filled triangle in space.