A rotating box

For our first foray into animation, we’ll create a box that rotates around the z-axis at the rate of one rotation every 5 seconds.

Rotating box

We use this function to create the box:

function makeRotatingBox() {
    let geom = new THREE.CubeGeometry(4, 1, 1);
    let mat = new THREE.MeshLambertMaterial({color: 'blue'});
    let box = new THREE.Mesh(geom, mat);
    box.rps = 0.2;
    return box;
}

This is similar to other mesh-construction functions we’ve written except that we attach the property rps to the box in line 5. Here we set rps, which stands for revolutions per second, to 0.2 since this translates to one full revolution every 5 seconds.

To get the box to rotate, we define an update function that gets called every time the frame gets repainted. This happens on the order of 60 times per second, though this rate may vary depending on scene complexity, device characteristics, and other things. We also need a clock to track how much time has passed since the last repaint.

let clock = new THREE.Clock();

function update() {
    let delta = clock.getDelta();
    let deltaRadians = rpsToRadians(box.rps, delta);
    box.rotation.z += deltaRadians;
    box.rotation.z %= 2 * Math.PI;
}

The call to clock.getDelta() returns the number of seconds that have elapsed since the last time it was called (or since the clock started if not yet called). We convert delta and the box’s rotation rate rps to its incremented rotation angle. And then we update the box’s rotation in z by this amount.

We also assume that box, constructed by calling makeRotatingBox, is a global variable which function update can access. And that box has been added to the scene which has already been created.

let box = makeRotatingBox();
scene.add(box);

The rpsToRadians function converts rotation rate and time to radians:

function rpsToRadians(rps, t) {
    return 2 * Math.PI * rps * t;
}

Lastly, we need to ensure that update gets called whenever the scene gets repainted. To do this, we set the renderer’s setAnimationLoop property to a function that takes no arguments. This callback function gets called automatically at every repaint.

renderer.setAnimationLoop(function () {
    update();
    renderer.render(scene, camera);
});

As we have seen, the call to update rotates the box. The call to renderer then repaints the scene as viewed from the camera, which we control as we orbit the scene.