Working with Angles in three.js with the Euler Class and various other features.

In three js there is the Euler Class that is the standard class in three.js that has to do with setting angles for the rotation of an object in three.js, or any other kind of task that would call for an instance of Euler. For example the rotation property of the Object3d class is an instance of Euler, and the Object3d class is a base Class for many objects in three.js including things like a Mesh, Groups, and Cameras just to name a few examples of the kinds of objects that are placed in a Scene. Speaking of Scene objects that too is an example of an object that is based off of the Object3d Class and thus also has a rotation property that is an instance of Euler.

The Euler class goes hand in hand with the Vector3 Class as the Euler class has to do with angles, while Vector3 has to do with a position. A great deal of what is done in three.js has to do with moving and rotating objects around, so Vector3 is what can be used to set a position, while Euler is what one will need to use to set the orientation of the object.

1 - The Euler Class in Three.js and what to know first

This is a post On the Euler Class in three.js, as such I trust that you have at least some background when it comes to the basics of three.js and javaScript in general. So if you are new to three.js you might want to start with some kind of getting started post on three.js in general as a basic starting point for the basics of setting up a scene and so forth.

The Euler Class is one of many basic classes that you should know about sooner or later, it might be best to learn a thing or two about the Euler class when you are first learning the basics of making mesh objects move, and rotate around as this is the class to do so when it comes to rotating at least.

The angles that are passed to the Euler class will be in the form or radians which is something that you should be familiar with not just for the sake of the Euler class, but for the sake of just about anything that has to do with angles in a javaScript environment.

1.1 - Version Numbers Matter with three.js

In this post I was using three.js r127, make sure that you are using that version if the code examples here are breaking for you. I can not say that much has changed with the Euler class specifically sense I started using threejs many years ago now, but that is certainly not the case with everything else in the library.

1.2 - The source code examples here are on Github

The source code examples for this post can be found in my test threejs Github repository.

2 - Basic example of The Euler Class, and the copy method

This will aim to be a basic getting started example of the Euler Class where I am creating an instance of THREE.Euler directly. Once I have an instance of Euler there is the question of what to do with it in a three.js example. With that said there is the copy method of a Euler instance that can be used to copy the state of one Euler Class to another. So in this example I am creating a Mesh with the Box Geometry Constructor and the Normal Material, and then making a few clones of the mesh with the mesh clone method. After that I am then using the copy method of the Euler instance that is located at the rotation property of the mesh objects to set some of them to the value that I have set with the single Euler Class instance.

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
35
36
37
// AN INSTANCE OF THREE.Euler
var euler = new THREE.Euler(Math.PI / 180 * 45, 0, 0)
// a Mesh
var meshA = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial());
// cloning ths mesh
var box1 = meshA.clone(),
box2 = meshA.clone(),
box3 = meshA.clone();
// USING THE INSTANCE OF EULER TO SET THE STATE
// OF THE EULER INSTANCES OF THESE MESH CLONES
box2.rotation.copy(euler);
box3.rotation.copy(euler);
// adjusting positions
box2.position.set(-1,0,0);
box3.position.set(1,0,0);
// creating a scene
var scene = new THREE.Scene();
// add the box mesh to the scene
scene.add(box1);
scene.add(box2);
scene.add(box3);
// camera and renderer
var camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(640, 480);
document.getElementById('demo').appendChild(renderer.domElement);
renderer.render(scene, camera);

For this example I am not doing anything fancy with an app loop, events, or anything to that effect. However the basic idea of what the Euler class is all about is there for what it is worth for starters. The copy method is one way to set the value of a Euler class instance such as the ones used for the rotation properties of these mesh clones as each one that I set with the Euler class instance that I made at the top is also rotated at a 45 degree angle. However maybe it would be a good idea to work out at least a few more examples that make use of the set method of the Euler class, and maybe a main app loop to start to make something interesting.

3 - The Euler x, y, and z props

One way to rotate objects would be to use the x, y, and z properties of the Euler instance that is located in the rotation projects of a Mesh, or anything that inherits from Object3d for that matter. This allows for a decent way to mutate values in place rather than setting them to a given set of values. For example I can just add a radian delta value to a given property to rotate the object on that axis.

In this example I once again have three mesh objects, this time though I have a basic application loop in which I am using request animation frame. Inside this loop function I am using the x, y, and z properties to rotate the mesh objects.

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
35
36
37
38
39
40
41
42
43
44
45
46
47
// a Mesh
var meshA = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial());
// cloning ths mesh
var box1 = meshA.clone(),
box2 = meshA.clone(),
box3 = meshA.clone();
// adjusting positions
box2.position.set(-1.5, 0, 0);
box3.position.set(1.5, 0, 0);
// creating a scene
var scene = new THREE.Scene();
// add the box mesh to the scene
scene.add(box1);
scene.add(box2);
scene.add(box3);
// camera and renderer
var camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(3, 3, 3);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(640, 480);
document.getElementById('demo').appendChild(renderer.domElement);
var lt = new Date();
var loop = function () {
var now = new Date(),
secs = (now - lt) / 1000;
requestAnimationFrame(loop);
if (secs >= 0.075) {
lt = now;
// USING EULER XYZ PROPS
box2.rotation.x += 1 * secs;
box2.rotation.x %= Math.PI * 2;
box3.rotation.y += 1 * secs;
box3.rotation.y %= Math.PI * 2;
renderer.render(scene, camera);
}
};
loop();

So then this is one way to go about rotating objects, but then there is also the set method that can also be used as a way to set the values of a Euler instance.

4 - Using the set method

On top of the properties of the Euler class instance there is also the set method that is another way to go about setting what the angles are for a Euler Class instance. For this I just call the set method of the Euler Instance and then pass and x, y, and z value as arguments in that order by default. A fourth argument can be used to set the order of these values, but the default setting is what I always seem to use for this.

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
35
36
37
38
39
40
41
// a Mesh
var meshA = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial());
// creating a scene
var scene = new THREE.Scene();
// add the box mesh to the scene
scene.add(meshA);
// camera and renderer
var camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(3, 3, 3);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(640, 480);
document.getElementById('demo').appendChild(renderer.domElement);
var lt = new Date();
var state = {
x: 0,
y: 0,
z: 0
};
var loop = function () {
var now = new Date(),
secs = (now - lt) / 1000;
requestAnimationFrame(loop);
if (secs >= 0.075) {
lt = now;
state.x += 0.5 * secs;
state.y += 1.0 * secs;
state.z += 1.5 * secs;
state.x %= Math.PI * 2;
// USING EULER SET METHOD
meshA.rotation.set(state.x, state.y, state.z);
renderer.render(scene, camera);
}
};
loop();

So now I have the basics of the Euler class out of the way, there are a few more methods but so far I can not say that I am using them that much in actual projects. For the most part I just want to use these methods to rotate some kind of object typically a mesh, but also groups and cameras.

5 - The Vector3 apply Euler method and setting position from Euler

There is not just working with this instance of the Euler class that is stored in the rotation property of an object based off of Object3d, there is also creating a stand alone instance of Euler. There are then a number of things that can be done with this instance of Euler such as passing it to another method of another class that expects an instance of Euler as one of the arguments. A good example of that kind of method might be the apply Euler method of the Vector3 class.

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
(function () {
// ---------- ----------
// Scene, Camera, and Renderer
// ---------- ----------
var scene = new THREE.Scene();
scene.add(new THREE.GridHelper())
var camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(3, 3, 3);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(640, 480);
document.getElementById('demo').appendChild(renderer.domElement);
// ---------- ----------
// Adding a Mesh
// ---------- ----------
var mesh = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial());
scene.add(mesh);
// ---------- ----------
// LOOP - Using Vector3.applyEuler with an instance of THREE.Euler
// ---------- ----------
var state = {
lt: new Date(),
fps: 24,
radian : 0,
euler : new THREE.Euler(0, 0, 0)
};
var loop = function () {
var now = new Date(),
secs = (now - state.lt) / 1000;
requestAnimationFrame(loop);
if (secs >= 1 / state.fps) {
// updating state.euler, and using Vector3.applyEuler with state.euler
// by way of mesh.position which is an instance of Vector3
state.euler.z += THREE.MathUtils.degToRad(90) * secs;
state.euler.z = THREE.MathUtils.euclideanModulo(state.euler.z, Math.PI * 2);
mesh.position.set(1, 0, 0);
mesh.position.applyEuler(state.euler);
// doing a spin also
mesh.rotation.y += THREE.MathUtils.degToRad(360) * secs;
mesh.rotation.y = THREE.MathUtils.euclideanModulo(mesh.rotation.y, Math.PI * 2);
// render
renderer.render(scene, camera);
state.lt = now;
}
};
loop();
}
());

Although something like this might work okay for setting the position of a mesh object by way of the Euler class and the Vector3 class apply Euler methods there are additional ways of doing this sort of thing. In the Vector3 class there is a set from spherical coords method for example that takes a radius and two angles to set a position.

6 - Conclusion

The Euler Class is something that I work with all the time when it comes to rotating an object in three.js. There is mainly just knowing the set and clone methods of the Class and that is it. At least those two methods are the ones that I find myself using in various projects thus far. There is also not just using the Euler class alone, but also working with the various other methods in the Vector3 class, as well as the Object3d class to preform all kinds of typical tasks that come up when working on a project that involves the use of threejs.

If you have not done so all ready it might make sense to also take a moment to look over the Vecor3 Class also when it comes to setting positions rather than the orientation of an object. Speaking of Objects there is also looking into the major base class of threejs that is Object3d, which contains the rotation property that is an instance of the Euler class used to rotate objects.