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

In threejs there is the Euler Class that is the standard class in threejs that has to do with setting angles for the rotation of an object. The use of the clas of object will also come into play for a wide range of other tasks that pop up now and then such as when using the apply euler method of the vector3 class.

The rotation property of the Object3d class is an instance of Euler, and the Object3d class is a base Class for many objects in threejs 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 threejs 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.

The Euler Class in threejs and what to know first

This is a post On the Euler Class in threejs, as such I trust that you have at least some background when it comes to the basics of threejs and javaScript in general. So if you are new to threejs you might want to start with some kind of getting started post on threejs 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.

The source code examples here are on Github

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

Version Numbers Matter with threejs

In this post I was using threejs r127, and the last time I cam around to do a little editing I was using r146. 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 - Some basic Examples of the Euler class in threejs

In this section I will be starting out with a few quick basic examples of the Euler class in threejs. For the most part this will involve the instance of the user class that is stored at the rotation property of an object3d based object such as a mesh object.

1.1 - 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 threejs 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
38
//-------- ----------
// SCENE, CAMERA, RENDERER
//-------- ----------
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGL1Renderer();
renderer.setSize(640, 480, false);
(document.getElementById('demo') || document.body).appendChild(renderer.domElement);
//-------- ----------
// EULER
//-------- ----------
// 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 this 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);
// add the box mesh to the scene
scene.add(box1);
scene.add(box2);
scene.add(box3);
//-------- ----------
// RENDER
//-------- ----------
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.

1.2 - 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
//-------- ----------
// SCENE, CAMERA, RENDERER
//-------- ----------
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGL1Renderer();
renderer.setSize(640, 480, false);
(document.getElementById('demo') || document.body).appendChild(renderer.domElement);
//-------- ----------
// EULER
//-------- ----------
// a Mesh
const meshA = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial());
// cloning ths mesh
const 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);
// add the box mesh to the scene
scene.add(box1);
scene.add(box2);
scene.add(box3);
//-------- ----------
// LOOP
//-------- ----------
let lt = new Date();
const loop = function () {
const 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.

1.3 - 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
42
43
44
//-------- ----------
// SCENE, CAMERA, RENDERER
//-------- ----------
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGL1Renderer();
renderer.setSize(640, 480, false);
(document.getElementById('demo') || document.body).appendChild(renderer.domElement);
//-------- ----------
// EULER
//-------- ----------
// a Mesh
const meshA = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial());
// add the box mesh to the scene
scene.add(meshA);
//-------- ----------
// LOOP
//-------- ----------
let lt = new Date();
const state = {
x: 0,
y: 0,
z: 0
};
const loop = function () {
const 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.

2 - 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
//-------- ----------
// SCENE, CAMERA, RENDERER
//-------- ----------
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, 320 / 240, 0.1, 1000);
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGL1Renderer();
renderer.setSize(640, 480, false);
(document.getElementById('demo') || document.body).appendChild(renderer.domElement);
// ---------- ----------
// Adding a Mesh
// ---------- ----------
const 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
// ---------- ----------
const state = {
lt: new Date(),
fps: 24,
radian : 0,
euler : new THREE.Euler(0, 0, 0)
};
const loop = function () {
const 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.

Conclusion

The Euler Class is something that I work with all the time when it comes to rotating an object in threejs. 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.