If we can combine two triangles into a square, we should be able to use triangles to build a cube. After all, a cube is just a mesh of six squares, suitably positioned.
Not surprisingly, the code for building a cube is more complex than that of a square. One approach assembles six squares in suitable positions and orientations. But we can’t do that yet since we haven’t yet talked about transforming shapes to new positions and orientations. So we’ll go about it by constructing an array of the cube’s 8 vertices and then building 12 triangles on those vertices, 2 triangles for each of the square’s 6 faces. Here’s the code:
function createCube() { let geom = new THREE.Geometry(); let coords = [-1.0, 1.0]; // construct the 8 vertices and push them into the geometry for (let x = 0; x < 2; x++) for (let y = 0; y < 2; y++) for (let z = 0; z < 2; z++) geom.vertices.push(new THREE.Vector3(coords[x], coords[y], coords[z])); // construct the 12 triangles let faces = [[0, 6, 4], // back face triangles [6, 0, 2], [1, 7, 3], // front [7, 1, 5], [5, 6, 7], // right [6, 5, 4], [1, 2, 0], // left [2, 1, 3], [2, 7, 6], // top [7, 2, 3], [5, 0, 4], // bottom [0, 5, 1]]; // push the 12 triangles into the geometry for (let i = 0; i < 12; i++) geom.faces.push(new THREE.Face3(faces[i][0], faces[i][1], faces[i][2])); // build an array mats of different colored materials let colorNames = ["red", "green", "blue", "yellow", "cyan", "magenta"]; let mats = colorNames.map(function(c) {return new THREE.MeshBasicMaterial({color: c});}); // assign materials to the 12 triangular faces for (let i = 0; i < 6; i++) for (let j = 0; j < 2; j++) geom.faces[2*i+j].materialIndex = i; let mesh = new THREE.Mesh(geom, mats); return mesh; }
There’s quite a bit going on here. A few points. First, the 8 vertices that live in the geometry’s vertices
array are implicitly number 0 through 7, based on the order they were inserted. When building the 12 triangular faces, this numbering is used to identify each triangle’s 3 vertices. For example, the first subarray [0, 6, 4]
builds a triangle on vertices numbered 0, 6, and 4, which makes up half of the cube’s back face. Here’s a picture of the numbering scheme.
Second, to build the array mats
of materials, we map a function over the array of color names: for each color name, we create a material of that color. (This is an example of functional programming.) Third, to assign each triangular face a material and hence a color, we assign the face’s materialIndex
an index into the color. As with the vertices, materials in array mats
are referred to by their position (index) in that array. As I said, there’s quite a bit going on here. But it works.