Not the Shortest Path: Animating Geospatial Data in Blender
Not the Shortest Path — Ep. 2 🌎 📡 💾
What is 'Not the Shortest Path'?
Welcome to the 3rd episode of Not the Shortest Path. Releasing a new episode every two weeks seems sustainable with my workload. Of course, it would be great to write every week consistently, but the extra time allows me to experiment a lot more.
The episode is a little shorter than the others. The main reason is that I did not spend more time working on my skills within Blender. Instead, I started working on an alternative approach using Mapbox-GL-JS. There’s a quick GIF of the video animation below.
I’m excited to share these experiments, but I thought it was necessary to complete the last episode with the Blender animation scripts I used.
Some Context
We covered the data pipeline I've been using to convert traditional GIS data for 3D animation within Blender. You can check them out you are interested in understanding what the CSVs used by the Blender scripts contain.
The last episode voluntarily hid the methods used to script the animations. I won't be digging too deep into Blender and getting some of the basics down here. There is probably an exaggerated ratio of code to text in the episode. If you want to get this running locally, please reach out. I'll do my best to help out. I intend to make the scripts available, but the gains of rambling about some of the internal details are simply uninteresting to me.
Side Note on Converting .fit
Alexis Pont (a friend and coworker at Anagraph) wanted to dabble in 3D animation of his Strava activities. Unfortunately, Alexis had an issue with his data being in the .fit format, perhaps because of his Suunto watch.
We thought it would be helpful to share the script he used to convert a directory of .fit files to GPX. Then, once converted, you can use the same data pipeline in the previous episode.
How to learn Scripting in Blender?
There's a lot of information available online, and you can probably get by with some experience and trial and error. Some fantastic tutorials are publicly available and cover incredibly creative and disparate ways of using the 3D render engine. If you want to dig deeper into scripting with Blender and want a more linear path, I would highly recommend the official course available in Blender studio called Scripting for Artists. I followed the lesson, and it helped me understand a lot of strange notions. I would recommend having some experience with Python to accelerate the learning curve and focus on Blender's particularities.
A First Attempt at Importing a Road Network
Before learning about Blender Add-Ons, I went completely berserk with my experimentations, and it spiraled downward from there. Applying good software engineering practices while testing different visual effects is challenging. Even getting the camera positioned without even starting to test out customs rigs is an art of itself. Moreso, the feedback times can become very long when waiting on Blender to render the result of large datasets.
Most of my first experiments were with the road network of downtown Oregon. Here's a look at the Blender script I initially used:
The monolithic script needs some refactoring. However, I discovered some key points that guided my add-ons later on.
- A data class for the object we want to create brings a specific discipline and structure to our script.
- The material function should be imported within the script and made accessible to all other custom scripts.
- We should figure out a way to externalize the actual initialization logic of our data and how we initialize it.
- Altogether avoiding hard-coded values can become extraordinarily daunting and perhaps even overwhelming for an outside user.
Oh, something that is a huge red flag and that I have only learned recently, we should not be using cylinders to represent our lines. Blender curve objects are more adapted to this type of representation. I just had no idea and have not taken the time to correct it.
The Structure of Custom Blender Add-Ons
The official Blender documentation does a great job at explaining how add-ons work. However, they assume an implicit understanding of the advantages of add-ons. The most crucial aspect of add-ons is creating highly advanced tools usable through the Blender GUI with minimal code. Another critical point is the discipline add-ons bring in defining our custom logic. Not only is our code made accessible through the GUI, but we can also re-use it from our custom scripts.
The more specific add-ons have to vary a few elements to understand. The simplest ones are composed of a simple register and unregister method which enables and disables your function within the engine:
bl_info = {
"name": "My Test Add-on",
"blender": (2, 80, 0),
"category": "Object",
}
def register():
print("Hello World")
def unregister():
print("Goodbye World")
However, most add-ons can are composed of 5 elements:
- The description contains the general information about our add-on.
- The variables define the options presented to an end-user.
- The execute method determines the precise instructions to follow.
- The register method so the engine can access our add-on.
- The unregister method so the engine can disable our add-on.
Refactoring the Road Network Import Script
The add-on should have many changes. However, we are improving upon the last custom script. I also introduced an attempt at adding some noise to the lines. The idea was to reproduce Craig Taylor's Coral Cities (more complicated than it looks!). The noise functions are not accessible through the GUI but can be by a custom script.
The GPX Animation Add-On
The GPX animation add-on is the one used to produce the header GIF. The TrackImporter
can be called from a script or directly within the GUI.
We can still improve the add-on. Notably, I lazily defined the number of frames based on the number of points within a track.
It was also my first time using the actual mesh data of a curve to simulate a 3D line. We could substitute the use of cylinders in the previous road network add-on with the code from thecreate_path
.
The Gradient Coloring by Distance from Point Add-On
During the attempt to replicate Craig Taylor's Coral Cities, I thought it would be a good idea to script out the coloring of the objects with an add-on. The script uses the currently selected objects and the defined point to calculate the distance used for the color gradient.
It turned out to be a relative waste of time because you can use the built-in Shader Editor within Blender to achieve a relatively similar effect. There are an insane amount of Youtube tutorials dedicated to this. Try the keywords: gradient color blender.
For the colors aspects, I added a new emission material to all the cubes and added an emission particle system all from within the GUI. Youtube tutorials are again a better reference than me here.
Conclusion
Displaying a result from geographic data is simple, but getting things to look picture perfect is tough. There is significant complexity in mastering the entire GIS data pipeline, but manoeuvering the 3D animation ecosystem might be even more challenging. I think it’s safe to say j’ai encore des croûtes à manger. From camera rigging to defining frames, there’s a tone to learn.
I’ve come to appreciate even more people’s creations working on animating geospatial data. However, there is a significant gap between the available tools that enable IT/GIS professionals to animate their data. We need motion designers’ new skillset to create engaging geospatial animations.
Or do we? The results might not be as custom and other-world looking as those done with a 3D render engine, but I seem to have stumbled upon an easier way to create simpler (still scripted) geospatial animations.
I would’ve never have thought of using my web browser to export videos directly. Here’s an animation of my ski-touring outing in Sutton using the more straightforward approach: