# Rotere 3D-figurer

Rotating things in three dimensions sounds complicated and it can be, but there are some simple rotations. For example, if we imagine rotating our cube around the z-axis (which points out of the screen), we are actually just rotating a square in two dimensions:

### A reason to learn trigonometry

Triangle diagram
We can simplify things further, by just looking at a single node at position (x, 0). Using simple trigonometry we can find that the position of the point after rotating it by θ around the origin is:
x, prime, equals, x, times, c, o, s, left parenthesis, theta, right parenthesis
y, prime, equals, x, times, s, i, n, left parenthesis, theta, right parenthesis
If you don't understand where these equations came from, this video might help.

### Rotating a point about the origin

Triangle diagram
The example above allows us to rotate a point that starts on the x-axis about the origin, but what if it isn't on the x-axis? This requires some slightly more advanced trigonometry. If we call the distance between the point (x, y) and the origin r, and the angle between the line to (x, y) and x-axis , then:
If we rotate by β to point (x', y'), then:
Using some trigonometric identities, we get:
Substituting in the values for x and y above, we get an equation for the new coordinates as a function of the old coordinates and the angle of rotation:

### Writing a rotate function

Now we know the mathematics, we can write a function to rotate a node, or even better, our array of nodes, around the z-axis. This function will loop through all the nodes in the node array, find its current x and y coordinates and then update them. We store sin(theta) and cos(theta) outside the loop so we only need to calculate them once:
var rotateZ3D = function(theta) {
var sinTheta = sin(theta);
var cosTheta = cos(theta);
for (var n = 0; n < nodes.length; n++) {
var node = nodes[n];
var x = node[0];
var y = node[1];
node[0] = x * cosTheta - y * sinTheta;
node[1] = y * cosTheta + x * sinTheta;
}
};
To rotate the cube by 30 degrees, we'll call the function like this:
rotateZ3D(30);
You can see the rotated cube below - it's slightly more interesting than before, but not by much:

### Rotating in three dimensions

We can now rotate our cube in two dimensions, but it still looks like a square. What if we want to rotate our cube around the y-axis (vertical axis)? If we imagine looking down on our cube as we rotate it around the y-axis, what we would see is a rotating square, just like we do when we rotate about the z-axis.
We can take our trigonometry and function from before, and just re-label the axis so that the z-axis becomes the y-axis. In this case, the y-coordinates of the node do not change, only the x and the z:
var rotateY3D = function(theta) {
var sinTheta = sin(theta);
var cosTheta = cos(theta);
for (var n = 0; n < nodes.length; n++) {
var node = nodes[n];
var x = node[0];
var z = node[2];
node[0] = x * cosTheta - z * sinTheta;
node[2] = z * cosTheta + x * sinTheta;
}
};
And we can use the same argument to create a function that rotates our cube around the x-axis:
var rotateX3D = function(theta) {
var sinTheta = sin(theta);
var cosTheta = cos(theta);
for (var n = 0; n < nodes.length; n++) {
var node = nodes[n];
var y = node[1];
var z = node[2];
node[1] = y * cosTheta - z * sinTheta;
node[2] = z * cosTheta + y * sinTheta;
}
};
Now that we have those functions defined, we can rotate 30 degrees by the two other axis:
rotateX3D(30);
rotateY3D(30);
You can see the complete code below. Try using the number scrubber to change the values in the function calls.

### User interaction

We can rotate the cube by adding function calls, but it's a lot more useful (and satisfying) if we can enable the viewer to rotate the cube using their mouse. For this we need to create a mouseDragged() function. This function is automatically called whenever the mouse is dragged.
mouseDragged = function() {
rotateY3D(mouseX - pmouseX);
rotateX3D(mouseY - pmouseY);
};
mouseX and mouseY are built-in variables that contain the current position of the mouse. pmouseX and pmouseY are built-in variables that contain the position of the mouse in the previous frame. So if the x-coordinate has increased (we move the mouse right), we send a postive value to rotateY3D() and rotate the cube counter-clockwise around the y-axis.
You can see for yourself below.