Animating objects with WebGL

Our existing code from the previous examples is already configured to redraw our WebGL scene every 15 milliseconds. Until now, it's simply redrawing everything exactly the same way every time. It's time to change that, so that our square actually moves.

In this example, we'll actually rotate and move our 2D square in all three dimensions; this will prove that even though we're only creating a 2D object, it still exists in 3D space.

Making the square rotate

Let's start by making the square rotate. The first thing we'll need is a variable in which to track the current rotation of the square:

JavaScript
var squareRotation = 0.0;

Now we need to update the drawScene() function to apply the current rotation to the square when drawing it. After translating to the initial drawing position for the square, we apply the rotation like this:

JavaScript
mvPushMatrix();
mvRotate(squareRotation, [1, 0, 1]);

This saves the current model-view matrix, then rotates the matrix by the current value of squareRotation, around the X and Z axes.

After drawing, we need to restore the original matrix:

JavaScript
mvPopMatrix();

We save and restore the original matrix to avoid having this rotation applied to other objects we might draw. No other items are drawn in this example so this serves no purpose here.

To actually animate, we need to add code that changes the value of squareRotation over time. We can do that by creating a new variable to track the time at which we last animated (let's call it lastSquareUpdateTime), then adding the following code to the end of the drawScene() function:

JavaScript
var currentTime = Date.now();
if (lastSquareUpdateTime) {
  var delta = currentTime - lastSquareUpdateTime;

  squareRotation += (30 * delta) / 1000.0;
}

lastSquareUpdateTime = currentTime;

This code uses the amount of time that's passed since the last time we updated the value of squareRotation to determine how far to rotate the square.

Making the square move

We can also move the square around by translating to a different position before drawing it. This example is going to do some very basic animation; obviously in the real world you'd want to do something less insane.

Let's track offsets to each axis for our translation in new variables:

JavaScript
var squareXOffset = 0.0;
var squareYOffset = 0.0;
var squareZOffset = 0.0;

And the amount by which to change our position on each axis in these variables:

JavaScript
var xIncValue = 0.2;
var yIncValue = -0.4;
var zIncValue = 0.3;

Now we can simply add this code to the previous code that updates the rotation:

JavaScript
squareXOffset += xIncValue * ((30 * delta) / 1000.0);
squareYOffset += yIncValue * ((30 * delta) / 1000.0);
squareZOffset += zIncValue * ((30 * delta) / 1000.0);

if (Math.abs(squareYOffset) > 2.5) {
  xIncValue = -xIncValue;
  yIncValue = -yIncValue;
  zIncValue = -zIncValue;
}

Finally, add the following to the drawScene() function:

JavaScript
mvTranslate([squareXOffset, squareYOffset, squareZOffset]);

This causes our square to zoom around, moving haphazardly around the context as well as toward and away from the viewer, all while rotating. It looks rather like a screen saver.

View the complete code | Open this demo on a new page

More matrix operations

This example uses a few additional matrix operations, including two routines to push and pop matrices from a stack to preserve them, and one that rotates a matrix a given number of degrees. These follow, for your reference:

JavaScript
var mvMatrixStack = [];

function mvPushMatrix(m) {
  if (m) {
    mvMatrixStack.push(m.dup());
    mvMatrix = m.dup();
  } else {
    mvMatrixStack.push(mvMatrix.dup());
  }
}

function mvPopMatrix() {
  if (!mvMatrixStack.length) {
    throw("Can't pop from an empty matrix stack.");
  }
  
  mvMatrix = mvMatrixStack.pop();
  return mvMatrix;
}

function mvRotate(angle, v) {
  var inRadians = angle * Math.PI / 180.0;
  
  var m = Matrix.Rotation(inRadians, $V([v[0], v[1], v[2]])).ensure4x4();
  multMatrix(m);
}

These routines were borrowed from a sample previously written by Vlad Vukićević.

License

© 2016 Mozilla Contributors
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-us/docs/web/api/webgl_api/tutorial/animating_objects_with_webgl

Tutorial WebGL