We called our createRing
program with a scene graph obj
representing a 2D slab of cubes. The program cloned obj
multiple times and rotated each copy into place. In effect, it added each rotated copy of obj
into a larger scene graph. But suppose we want a series of objects rotated around a common axis but we want the objects to vary. In this case, repeatedly adding clones of the same object will not do.
One way to achieve this is to write a createRingF
function that gets called with an ‘object construction’ function fnc. Every time createRingF
needs to rotate another object into place, it calls fnc to get a new object. The difference is that createRingF
gets new objects by calling fnc rather than cloning the same object repeatedly as is done in createRing.
function createRingF(fnc, n, t) { let root = new THREE.Object3D(); let angleStep = 2 * Math.PI / n; for (let i = 0, a = 0; i < n; i++, a += angleStep) { let s = new THREE.Object3D(); s.rotation.y = a; let m = fnc(i, n); m.position.x = t; s.add(m); root.add(s); } return root; }
Note createRingF
‘s similarity to createRing.
Really, the only difference is in the object-creation call on line 7.
To test createRingF,
we write an object-creation function that generates each of the five Platonic solids in turn.
function makeSolidsFnc() { const solids = [ new THREE.TetrahedronGeometry(1), new THREE.BoxGeometry(1, 1, 1), new THREE.OctahedronGeometry(1), new THREE.IcosahedronGeometry(1), new THREE.DodecahedronGeometry(1) ]; const nbrSolids = solids.length; function f(i, n) { let geom = solids[i % nbrSolids]; let color = new THREE.Color().setHSL(i/n, 1.0, 0.5); let args = {color: color, opacity: 0.8, transparent: true}; let mat = new THREE.MeshLambertMaterial(args); return new THREE.Mesh(geom, mat); } return f; } let solidsFnc = makeSolidsFnc();
Here, solidsFnc(i, n)
returns the Platonic solid indexed by i%5 (the array solids
is indexed by integers 0 through 4). Where n meshes are produced in total, the i’th mesh is assigned the hue i/n, where hues range across the color spectrum as values go from 0 to 1. This is how we get the rainbow effect.
Calling createRing(solidsFnc, 20, 10)
produces the ring shown in this program: