WebGL animations

Carlos Eduardo González Alvarez
cegonzalez13
Published in
6 min readMar 22, 2018

Loading curves and showing non-symmetrical objects following this curves in WebGL.

In this example we are going to implement a basic movement animation in WebGL, based on some points the user is going to define and transforming them to points defined by its bezier curves. The final result can be found here, and we can see the animation running down here:

The example is based on a WebGL Fundamentals course on 3d Objects, just for rendering the F object and having access to the translation in x, y and z. It is also avaliable here:

With just the example implemented in our codepen, we would have a good looking, but static F object. This is because the translation and rotation variables are not changing over time. In order to do this, first we need to add the variables by default for them to change in our render function:

As we can see, first we are setting up the variables for the properties of our object. The translation sets the initial x, y and z position. We put 50 in z position for it to be a little bit away from the screen, to create a 3D perspective. Then we set the rotation and scale, just to make the F present itself in a good angle. The fudgefactor lets us present the F as a 3d object by making the object larger when it is closer to the screen and smaller when it is away. The then and puntoActual are variables that are going to be explained in the render function, which we are going to present next. The puntosIniciales variable is simply the two main points by default that the F is going to go through. The neat thing about this project is that we can add infinite points to this variable for the F to move through!

Calculating the Bezier curve points

In order for our animation to look the more natural way possible, we need to interpolate some points that make up for the curve that is going to be generated from the initial points we set up. In other words, we need to make curves our of the lines that connect the dots that our F is going to pass through. This is done by calculating the bezier curve points.

In order to do this, I took as an example the WebGL fundamentals lesson on Bezier curves and took out the functions that receive some points as a parameters and output another series of points that define its bezier curve. So, the first thing we do is make the transformation from the initial points (called puntosIniciales) to the points that make up for the curve, and then we define the functions we are using:

Firstly, we see the tolerance and distance parameters. The tolerance is going to define the maximum flatness for a line connecting two points, to determine if we are going to call the bezier function over this line or not. The distance is the maximum distance between two points in the bezier curve we are going to define. If we increment this value, we will have less points and less detail for our curve, so we want it to be a low value.

Now, for the logic of the functions we execute, we are just going to focus on the usage of the lerp function. The rest of the calculation can be explained on further detail here, but we are going to leave this graphic so you can see the main mathematical idea behind the functions:

Lerp function

Lerping is a common term in animation. It means linear interpolation, and it is the main function that lets us calculate the points for our Bezier curve. The function utilized in the example can be found here:

We added some constraints for our values not to be undefined, but the main thing that we need to know is that the function is taking three values, the a and b values are the points that we are going to interpolate, and the t value is a value from 0 to 1 that defines how far along the line connecting the two dots we are. This is crucial for the bezier curve to work, because it sets up each curve we calculate between two points .

Rendering

Instead of calling drawScene every time we want something to change, we can use a render function that calls this drawScene every time it can, and we can change the variables every time the render function is called. This is the key for the animation to work. Aditionally, we need to set the delta time that has passed since the last render, to work in terms of time and not in fixed values. This makes our animation change over time without it being laggy.

The scene is now drawed repetitively by calling the render function every time it can perform it. Note that we use the then variable to set the previous time for the last render we called. Then, we calculate the deltaTime that has passed since the last time we called the render function and now. Finally, we update the animation variables and we draw our scene based on the variables we changed.

Animation

In the animation function, we are just changing the variables we previously defined over time. This is done by variable:

The main thing that we are doing here is changing the translation (position) in term of a part of the distance that we have to cover to go from one point to another. Keep in mind that we are already using our bezier curve points.

This is done by first defining the value of x that we are going to increment based on the distance between the second point and the first point. We do this for y too and we call them deltaX and deltaY. For every change increment, we need to update the deltaX and delta Y and see if they already got to the target point. If they both did, we change the current point index, so the F can begin to move to the next defined point.

DrawScene

Now, we have to draw our object in terms of the variables we defined. This is going to be executed just after the updateAnimation function, and its also going to be executed repeatedly. The part that we need to look at is the part where we use the variables we defined:

UI Changes

Finally, we have done some UI changes in order for the user to be able to add his own points to the puntosInicales variable. We can see it here:

We are creating the html for printing out the points that we currently have, and then we create an event Listener for the whole canvas, that checks the x and y value that we inputted and adds them to the puntos array by calculating all the bezier curve points again. Thankfully the continous render lets us change the variable without having the need of calling the drawScene function again.

Finally, we added a reset button for the points to be erased and get the default points again:

Conclusion and time log

We managed to add a simple movement animation so an asymmetrical object can follow a path defined by some points that transformed to some other points by a function called the Bezier function, that lets us interpolate our points and add curvature to them for the transition from one point to another.

With the help of the functions defined in the WebGL example we needed some time of execution. I estimated 7 hours for the developement of this example, considering the complexity of calculating the curves, but the defined functions made it fairly simple so it didn’t took long to do the calculation, but the ui part to setup the points according to the user’s clicks took most of my time, so I ended up doing 10 hours of work.

--

--