3D Tutorial 3: Rotation

Onwards and upwards! Well... Not upwards. As you know, upwards depends on where our camera is facing!

Before we jump into controlling a camera in 3D space, we're going to look at something really quite awesome which will bring our 3D project to life.

We're back to our original cube project again! Below is the project we'll begin with, it should look very familiar by now!

Type, or copy and paste the following into the FUZE4 Nintendo Switch code editor.

  1. obj = placeObject( cube, { 0, 0, 0 }, { 1, 1, 1 } )
  2. setObjectMaterial( obj, red, 1, 1 )
  3. setCamera( { 0, 5, 10 }, { 0, 0, 0 } )
  4. pointLight( { 0, 4, 0 }, white, 100 )
  5.
  6. loop
  7.     clear()
  8.     rotateObject( obj, { 0, 1, 0 }, 1 )
  9.     drawObjects()
 10.     update()
 11. repeat

rotateObject()

Our new line in question is line 8.

  8.     rotateObject( obj, { 0, 1, 0 }, 1 )

The rotateObject() function is used to rotate an object, just as the name implies!

The first argument is the name of the variable which stores our shape. Ours is called obj.

The second argument is a vector which describes the axis or axes of rotation. In our example, we are going to rotate the cube around the y axis only, so the y element of this vector is 1, while the rest are 0.

Lastly, we have the amount of rotation per frame of animation. This argument is an amount of degrees. As you can see, we have used a 1 here, meaning our cube will rotate by 1 degree every frame.

Run the program to see a lovely spinning cube.

Alright! Now we've got that, let's experiment with the other axes.

To make an object rotate in the opposite way, simply use a negative number in the vector.

For example:

  8.     rotateObject( obj, { -1, 1, 1 }, 1 )

In the above, we are rotating negatively on the x axis and positively on both the y and z axes.

Rotating multiple shapes

Let's adapt these concepts into a slightly more impressive project. We can store a number of shapes in an array, then apply these techniques to all of them using for loops.

Type, or copy and paste the code below into the FUZE4 Nintendo Switch code editor:

  1. setCamera( { 0, 5, 20 }, { 0, 0, 0 } )
  2. pointLight( { 0, 4, 4 }, white, 100 )
  3.
  4. numShapes = 6
  5. array shapes[numShapes]
  6.
  7. for i = 0 to len( shapes ) loop
  8.     shapes[i] = placeObject( pyramid, { -numShapes - 1 + i * 3, 0, 0 }, { 1, 1, 1 } )
  9.     setObjectMaterial( shapes[i], fuzeblue, 0, 1 )
 10. repeat
 11.
 12. loop
 13.     clear()
 14.
 15.     for i = 0 to len( shapes ) loop
 16.         rotateObject( shapes[i], { 1, 1, 1 }, 1 )
 17.     repeat
 18.
 19.     drawObjects()
 20.     update()
 21. repeat

Running this program will give us 6 spinning pyramids.

We should be familiar with the first couple of lines from the previous tutorials. Let's go over creating the array and populating it:

  4. numShapes = 6
  5. array shapes[numShapes]

Here we create a simple one-dimensional array, with numShapes amount of elements. To change the number of shapes on screen, simply change the numShapes variable!

  7. for i = 0 to len( shapes ) loop
  8.     shapes[i] = placeObject( pyramid, { -numShapes - 1 + i * 3, 0, 0 }, { 1, 1, 1 } )
  9.     setObjectMaterial( shapes[i], fuzeblue, 0, 1 )
 10. repeat

Here, we use a for loop to populate the array with information. We call the placeObject() and setObjectMaterial() functions for each element of the array.

Notice the position vector on line 8: {-numShapes - 1 + i * 3, 0, 0}

The -numShapes - 1 + i * 3 used in the x element of the vector will position the shapes differently depending on the number of shapes on screen.

This is designed to space 6 shapes evenly across the screen.

Next up, we have our good old clear() and update() loop, inside which is a for loop making the magic happen.

 15.     for i = 0 to len( shapes ) loop
 16.         rotateObject( shapes[i], { 1, 1, 1 }, 1 )
 17.     repeat

For each shape in our array, we call a rotateObject() function, applying 1 degree of rotation on each axis per frame.

Using the Control Stick to Rotate an Object

Let's adapt this project to control the rotation using our Joy-Con control stick.

To achieve this, we'll only need a couple of extra lines, including the good old controls() function.

  1. setCamera( { 0, 5, 20 }, { 0, 0, 0 } )
  2. pointLight( { 0, 4, 4 }, white, 100 )
  3.
  4. numShapes = 6
  5. array shapes[numShapes]
  6.
  7. for i = 0 to len( shapes ) loop
  8.     shapes[i] = placeObject( pyramid, { -numShapes - 1 + i * 3, 0, 0 }, { 1, 1, 1 } )
  9.     setObjectMaterial( shapes[i], fuzeblue, 0, 1 )
 10. repeat
 11.
 12. loop
 13.     clear()
 14. 
 15.     j = controls( 0 )
 16.
 17.     for i = 0 to len( shapes ) loop
 18.         rotateObject( shapes[i], { 0, 1, 0 }, j.lx )
 19.         rotateObject( shapes[i], { 1, 0, 0 }, -j.ry )
 20.     repeat
 21.
 22.     drawObjects()
 23.     update()
 24. repeat

Very cool!

We simply call the controls() function, assign the result to a variable, then use the j.lx and j.ry values in our degrees of rotation argument.

Can you add a way of manually rotating the shapes on the z axis?

See you in the next tutorial where we'll be looking at creating camera controls!

Functions and Keywords used in this Tutorial

array, clear(), controls(), drawObjects(), loop, placeObject(), pointLight(), repeat, rotateObject(), setOBjectMaterial(), setCamera(), update()