Transforming spaces

So far, basic 3D geometries we’ve designed ourselves, such as cubes and pyramids, have been centered at the origin with symmetry axes aligned with the world axes (e.g., the pyramid’s axis aligns with the vertical y-axis). This is also true of the geometries generated by three.js, such as cylinders and toroids. This is sensible, since it’s easier both to design and to use geometries that are placed in a coordinate system that is natural to the geometry. However, we also need to be able to control the position and orientation of 3D objects. And we would like to do so not only with respect to the world coordinate system (represented in our programs by the red-green-blue axes), but also with respect to other coordinate systems. To accomplish this, we construct and manipulate a hierarchy known as a scene graph.

Each of our programs has in fact defined a scene graph: They have added meshes and light sources to the scene, resulting in very shallow hierarchies. Generally, scene graphs can grow to arbitrary breadth and depth. But before we look at scene graphs, we’ll look at transformations which are used to move and position objects and, as we’ll see, to define new coordinate systems.

Consider a long box that is centered at (4,0,0) and rotated by 30° counterclockwise around the z-axis.

A red box

This scene is achieved with this code:

let geom = new THREE.CubeGeometry(1, 1, 1);
let args = {color: 'red', transparent: true, opacity: 0.8};
let redMat = new THREE.MeshLambertMaterial(args);
let thirtyDegs = Math.PI / 6;

let redBox = new THREE.Mesh(geom, redMat);
redBox.position.x = 4;
redBox.rotation.z = thirtyDegs;
redBox.scale.x = 3;

We transformed the mesh redBox by setting its position, rotation, and scale properties. There are two ways of thinking about this. First using an object-based interpretation. We start with a red cube. And then, relative to the world coordinate system, we scale it by 3 units along the x-axis, and then rotate the scaled red box by 30° counterclockwise around the (blue) z-axis, and lastly translate it by 4 units along the (red) x-axis. Where T, R, and S stand for translation, rotation, and scale, we perform T·R·S(obj) right-to-left, from the inside out: First scale the object, then rotate the scaled object by 30°, and then translate the rotated-scaled object by 4 units, all with respect to the fixed world coordinate axes. The order is important since changing the order changes the net effect in general.

The second way to understand these transformations is using a system-based interpretation . Starting with the world coordinate system, we perform a series of transformations on the coordinate system itself. When we reach the object, we build the object in the resulting object coordinate system, centered at this system’s origin and aligned with its axes. We think of performing T·R·S(obj) left-to-right, from the outside in: First translate the parent coordinate system by 4 units, and then rotate the current (translated) coordinate system by 30° around the z axis, and then scale this translated-rotated coordinate system 30° counterclockwise around its z-axis. Finally, we construct the object centered and aligned to this new coordinate system.

Here’s a simple animation that shows the different between these two interpretations:

Two interpretations