The Object3D Base Class in three.js

The Object3D base class in three.js is one of the most important classes to be aware of when making some kind of project involving three.js. It is in use in many objects in three.js including things like cameras, lights, and the the Meshes that are placed in a Scene.

The Object3d class adds a whole bunch of common properties, and methods for any kind of object in a project that needs to have a position in the scene. Properties of the Object3d class can be used to set the position, and rotation of an object along with many other common things that are shared across all such objects in a scene. Once you know a thing or two about Object3D the same methods will work with any and all objects that inherent from Object3D, which is a lot so lets get started.

1 - What to know before hand

This is not a getting started post on three.js, or javaScript in general. This post is on an advanced topic on three.js and I expect that you have some basic working knowledge of what there is to know before hand.

As with any post on three.js the version number matters a lot, when I first started this post I was using three.js r91, and the last time I updated the post I was using r111 of threejs. Threejs is a project in motion so if any code in this post or any other threejs post breaks it might very well be because of the version number.

2 - Basic example of Object3d using the position property

Typically I do not work with the class directly, I work with something that inherits properties and methods from Object3d. Still if for some reason I want to work with the class directly I can do so via the THREE.Object3d constructor.

1
2
3
4
5
6
7
8
9
10
// Object 3d position
var obj3d = new THREE.Object3D();
// {"x":0,"y":0,"z":0}
console.log(JSON.stringify(obj3d.position));
obj3d.position.set(3, 4, 5);
// {"x":3,"y":4,"z":5}
console.log(JSON.stringify(obj3d.position));

Here I made just a simple example where I am just playing with the position property, which is an instance of Vector3. Vector3 is yet another class in threejs that a developer should be familiar with as it has to do with a single point in 3d space, so it goes without saying that class will come up a lot also.

The position property of Object3d can be used to set the center point of the object in a Scene. In the case that the Object is a child of another object it would be the position relative to the parent Object.

3 - Rotation of an Object

Another property of the Object3D base class that I use often is the rotation property. This property expects an instance of the Euler Class, Which is the Class used in three.js that has anything to do with a set of Euler Angles.

1
2
3
4
5
6
7
8
9
10
// creating an instance of Object3D
var obj = new THREE.Object3D();
//{"_x":0,"_y":0,"_z":0,"_order":"XYZ"}
console.log(JSON.stringify(obj.rotation));
obj.rotation.set(0, 0, Math.PI * 1.75);
// {"_x":0,"_y":0,"_z":5.497787143782138,"_order":"XYZ"}
console.log(JSON.stringify(obj.rotation));

I will not get into the Euler Class in detail here, but it is similar to Vector3 only when using the set method you want to give radians rather than, and x, y, z position in the scene.

4 - Examples of use in other constructors

There are many objects in three.js that inherit from object3D, which is why this is a good class to have a solid understanding of.

Camera’s such as the perspective camera inherit from Object3D

1
2
3
4
// Camera
var camera = new THREE.PerspectiveCamera(45, 4 / 3, .5, 100);
// changing position of a camera
camera.position.set(3, 1, 3);

Anything that is contained in a mesh also inherits from the Object3d class.

1
2
3
4
5
6
7
var low = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({
emissive: 0x002a00
}));
// changing position of a mesh
low.position.y = -1;

There are also various lights and helper objects also that all inherit from Object3d. So the Object3d class is a common class that can be used to move, and rotate any and all objects in a scene.

5 - Full demo of Object3D that uses the class as a way to group

The Three.Group constructor also inherits from Object3d and is a way of grouping objects together into a collection. However the add method of Object3d is in all objects that inherit from Object3d, and as such grouping can be done with any such object, including just a stand alone instance of Object3d.

I try to make it a habit to have at least one copy and past working demo of what it is that I am writing about in each blog post of mine. In this demo I am making use of an instance of Object3D to group some cubes together. I am also working with many other objects that inherit from Object3D, using the position, and rotation properties often.

5.1 - A Create Cube Stack method

So I started off this example of Object3d by creating an createCubeStack helper method. This method will return an object that contains a group property that is what will be added to the scene later on, and also a set method that can be used to change the stack of the stack relative to a value between zero and one.

In this helper I am also using the clone method of a mesh to create a copy of an original mesh that is then mutated just slightly and then added to the group created with the Object3d constructor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// create cube stack method
var createCubeStack = function (original) {
var stack = {},
original = original || new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial()),
cube;
// the group
stack.group = new THREE.Object3D();
// set method
stack.set = function (per) {
var bias = 1 - Math.abs(0.5 - per) / 0.5,
arr = stack.group.children,
len = arr.length;
arr.forEach(function (cube, i) {
var y = -len / 2 + i + 2 * bias;
cube.position.set(0, y, 0);
cube.rotation.set(0, Math.PI * 2 * (i / len) + Math.PI * 2 * per, 0);
});
};
// create cubes for the group
var i = 0,
len = 3,
per;
while (i < len) {
per = i / len;
cube = original.clone();
cube.position.set(0, -len / 2 + i, 0);
cube.rotation.set(0, Math.PI * 2 * per, 0);
stack.group.add(cube)
i += 1;
}
return stack;
};

So now that I have a helper method worked out it would be nice to test it out with a scene, renderer, and main app loop, so lets take a look at that then.

5.2 - The rest of the Object3d example

So then here I have the rest of the example that makes use of the create cube stack helper. I create a scene, camera, and renderer just like with any threejs example. However I now use my create cube stack helper to create an cube stack object which contains a group property. That group property is then what I add to the scene, and the set method of the cube stack object is what I use to update the stack in a main app loop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Scene
var scene = new THREE.Scene();
// Camera
var camera = new THREE.PerspectiveCamera(45, 4 / 3, .5, 100);
camera.position.set(5, 5, 5);
camera.lookAt(0, 0, 0);
var stack = createCubeStack();
scene.add(stack.group);
// Render
var renderer = new THREE.WebGLRenderer();
renderer.setSize(320, 240);
document.getElementById('demo').appendChild(renderer.domElement);
// loop
var frame = 0,
maxFrame = 100;
var loop = function () {
requestAnimationFrame(loop);
renderer.render(scene, camera);
stack.set(frame / maxFrame);
frame += 1;
frame = frame % maxFrame;
};
renderer.render(scene, camera);
loop();

When this example is up and running I get a stack of cubes rotating around and moving up and down. Thanks to the position, and rotation properties of the Object3d class.

It may be true that Object3D by itself is not intended to be used from grouping as there is a separate constructor for that, called simply enough Group. Still Object3D by itself seems to work okay by itself good enough for this simple demo on Object3D.

6 - Conclusion

From here you might choose to make some more demos that have to do with exercising the use of working with objects in three.js. If you enjoyed this post you might also like to check out my many other posts on the subject of threejs and javaScript.