ArcGIS Maps SDK for JavaScript

Bring your 3D web applications to life with mesh animations

Animations can guide the user to better understand how to interact with an application, how the data is changing over time or how something works. Animations are not limited to motion, but in this blog post we will tackle the specific use case of animating a 3D mesh by translating, rotating or scaling it. I’m excited about this new capability in the ArcGIS Maps SDK for JavaScript because I believe such animations can bring a web scene to life (even though it’s a very niche side of animations).

The main idea is that we load a gltf model as a Mesh and then we apply a transformation on every frame using MeshTransform. With version 4.30, ArcGIS Maps SDK for JavaScript supports fast updates to translate, rotate or scale the mesh.

Important disclaimers:

With that out of the way, let’s look at a few possible animations. Here is a video of a small application I built, where I show examples of such animations:

Keep reading if you want to look into how you can create each one of these animations. But if you just want to look at the code, it lives on GitHub.

Animate with rotation

Did it ever happen to you that you wanted to have a 3D object as a symbol, but from certain angles the object doesn’t look recognisable? Let’s say you want to display a 3D pin point to mark a location. If we look at it from the side, we can’t really tell that it’s a pin point:

To align the pin point to face the camera, we’ll watch for changes in the camera heading and rotate the pin point accordingly. This means that we’ll rotate it around the z axis with an angle that is the negative of the heading. I am adding a few degrees more because I like to see it a bit from the side to show its 3D shape:

Let’s look at another use case for rotation: a wind turbine. I purchased an offshore wind turbine on Sketchfab. To make the blades rotate, I used Blender to separate them from the tower and I exported both the tower and the blades as separate glb models. The tower is loaded as a 3D object symbol layer, as it consumes less memory and the blades are individual mesh graphics, loaded using the Mesh.createFromGLTF method. Each graphic has a given wind speed and we use it to calculate the revolutions per minute using this formula: RPM = (60 * wind speed * TSR) / (Math.PI * 2 * blade length). The blade length is in meters, wind speed is expressed in meters/second. The tip speed ratio (TSR) is the ratio between the tangential speed of the tip of the blade and the actual speed of the wind. Normally it’s somewhere between 6 and 9.

To create the animation we need to calculate the angle of rotation on the y axis based on the elapsed time since the animation started and the RPM value. RPM tells us how many full rotations a blade does in one minute. So the rotation angle will be bladeRotationAngle = elapsedTime * RPM * 360, where elapsedTime is expressed in minutes. I am multiplying by 360 because the rotation takes an angle in degrees.

We then apply the transformation and we make sure the same calculation runs again on the next frame:

Rotation around multiple axes

I added a boat to the 3D diorama and initially, I made it move up and down to mimic the wave movement. But when I showed it to my colleague Hugo, he said: Raluca, we need to add pitch and roll!

A rotation around an axis obtained by composing x and y is done using quaternions. I won’t attempt to explain them in this blog post, but I’ll drop a link to the best explanation I could find. Basically a quaternion is represented by the formula:q = cos(θ/2) + sin(θ/2)*(ux*i + uy*i + uz*k) where ux, uy, uz are the components of the axis around which we want to rotate and is θ the angle of rotation in degrees. In JavaScript you don’t need to calculate the angle and the rotation axes yourself, you can use a library called GLMatrix that does the calculation. The angle is dependent on the elapsed time and it’s used to calculate waveX, waveY and waveZ.

Animate with scale

How can we use scaling? We could use it to give the user clues on what can be clicked by increasing the size of an object on mouse hover. We could also resize it proportionally to the distance to the camera, so that it’s always visible as we zoom out (we could make it behave like screen space symbols that always keep the same size on screen). In our example we make the 3D pin point pulsate to draw the user’s attention to that location.

The first thing that comes to mind when I think of something decreasing and increasing is a sinusoidal function. The easiest way to create a pulsation of a 3D object is by scaling it using Math.sin(elapsedTime). Then we pass it into the transform property of the Mesh geometry:

Animate with translation

Moving a 3D object along a predefined trajectory is probably one of the most common use cases. In this example we’ll move a submarine along a predefined line. In our fantasy 3D diorama world, we let the submarine travel with 360km/h (that is about 220mph). And every frame we calculate the new position in which we should place it. This technique is taken from Arno’s example where he animates a line to draw itself. The steps are:

In case you’ll be using this technique, I’d love to know about it! In the meantime, I’ll leave you with the link to the application and the link to the code.

About the author

Raluca works as a web cartographer with the Geo Experience Center team at Esri. She loves to play around with web technologies and visualization styles. If she's not in front of the computer, she's probably somewhere up in the mountains.

Connect:
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments

Next Article

Basemap Releases Include Over 180 New and Updated Communities

Read this article