3D Made Easy: Don’t Fear the JSON
Does technology scare you? Do you feel left behind by progress? When you see a cool and clever use of spatial tech, are you not so much inspired as intimidated?
If so, you might – like me – be wary of trying out 3D. It’s not the data that is intimidating, it’s the technology involved. I want something cool like Batman’s sonar cell phones, and instead I end up that guy on failblog under the heading “Watch a four-year-old rip this dudes GeoJSON to shreds!”
But I figured I really had to do a 3D article at some point, so I sat down to it and the funny thing is – once I got a little help – it was fun and fairly easy.
Personally I’m amused at Minecraft’s block-like appearance. It’s like a regression to the video games I played in the 80’s and 90’s – but it does undoubtedly show there is an incredible appetite for 3D environments.
Right now it’s hard to fully satisfy that appetite because we’re all into web 2.0 and mobile devices, and 3D data hasn’t quite made that leap. It’s got a way to go in terms of data formats that can be streamed and tools that can visualize that streamed data (without plugins).
It’s like 2D maps, which we all knew ages ago were going to be huge, we just had to wait for the technology – and worldwide public use of it – to catch on.
And 3D is now catching on.
In the mainstream there are hardware products, like the Samsung/Oculus headset (virtual reality) and Microsoft Hololens (mixed reality). Then there is an organization called Magic Leap. I have very little idea what they are about, but it looks incredible and, frankly, it feels astonishing that I even inhabit the same planet as people with this sort of imagination!
But those are projects with public visibility. If we pay attention to the “man behind the curtain” there are some up and coming software tools for handling 3D data.
Let’s be clear, Cesium and three.js are not data formats. Neither are they applications. They are programming tools that developers can use to read your data into a web browser and visualize it.
Think of Cesium (click image to enlarge) as a globe/map/3D visualization environment (give it a try) that’s optimized for spatial data. It has its own CZML format (again JSON based) and can also use other data sources like Collada, OpenStreetMap, and WMS.
If that’s confusing to you, don’t worry! I see the future being two separate roles: the web developers who create applications using tools like Cesium and three.js, (here, for instance is a web site powered by three.js) and the spatial folk who create the 3D models that these applications consume.
Luckily there is FME. FME is designed to translate and transform data – both spatial and tabular – from all these different systems, merging and filtering as it goes. The two concepts are natural partners. FME provides the data that powers these 3D toolkits.
We implemented three.js support in FME2015.1, for instance, and the following example shows how simple it is.
three.js: The FME Part
OK, the FME technology we’re going to use is the JSONTemplater transformer. So – and I assume here you have some FME experience – simply read your 3D data into the workspace, and then run it into a JSONTemplater transformer, like so:
Notice that, because we need to write out the JSON we create, I follow it up with a Text File Writer.
The parameters for the JSONTemplater look like this:
Note, because we’re writing to the text file, I write the results to an attribute called text_line_data.
The template I use is like this:
fme:get-threejs-geometry( "C:MyModel extures" )
The first part tells FME to convert the feature geometry to JSON that is compatible with threejs (this function is what’s new in 2015.1). The second part tells the web site where you are going to store any textures. The web server needs to be able to find it, so it’s something you’d agree on in advance with your web developer.
And that’s it. Run the workspace and you have a web-ready JSON dataset.
three.js: The Web Part
I’ll mention this only briefly, enough for a non-web person to understand and hopefully implement what I did. The steps are as follows:
- First you need a web server. I’m going with Tomcat because FME Server has thoughtfully already installed it for me! So if in doubt, just install FME Server.
- Secondly you need the three.js files. Download them and put them into the root folder of your web server. You can see that I just copied these two files and discarded the rest:
- Copy your JSON dataset to the web server – I put mine under …ROOTmodelsMyModel
- Copy your textures to the web server – I put mine under …ROOTmodelsMyModelTextures
- Create a web page. The web page will use three.js functionality to load the model and render it in 3D.
The three.js website has a lot of documentation and examples, but this is what I did: I copied someone else’s code! It’s this file here and I got it from a colleague at Safe. The important part is:
var loader = new THREE.JSONLoader(true); loader.load("models/MyModel/model.json", final_load, "./models/MyModel/textures/" );
Now I just have to open that file through my web server. In my case I just browsed to: http://localhost/MyScript.html
three.js: Return of the Sundial
Do you remember my last blog post? The one about creating a virtual sundial. Well, that’s what I ran this example on. This is the workspace (click to enlarge):
It’s not quite “ten transformers or fewer” but only two or three are related to the three.js requirements (the rest are all about creating the sundial).
The one issue that stalled me for ages is this: three.js only allows a single object (feature) per JSON file. So that’s what the Aggregator transformer is for.
The other point to note is that three.js doesn’t support double-sided faces, so my sundial gnomon is actually made up of two features, one the mirror image of the other.
I was going to show a screenshot of the output – but when the whole point of this article is putting 3D models into a web browser… well it didn’t seem right.
So here’s the model itself:
NB: Left-click, right-click, and middle-click all have different viewing operations.
So now I have an FME workspace that generates a 3D model on the fly (using a Python script, if you remember, that calculates the position of the sun) and pushes that model out to a form of JSON that can be consumed with three.js
As I said before, you probably won’t be carrying out this type of project just to model garden ornaments. But! I hope having seen this, and how relatively easy it was, you’ll be inspired (and not intimidated) and think about how you might use 3D capabilities within your own organization.
Because my sundial records the time, you can actually see it was created at just before 3am/pm. Now it’s true that a static sundial must be right at least twice a day, but wouldn’t it be better if the three.js model was showing the actual time?
Well that’s going to be the next post I write. I’m going to try and get the workspace into FME Server, and set up the web page to fetch the dataset automatically. That way 3D model will dynamically update to the actual time!
Further Reading (or Viewing)
An FME-generated Rubik’s Cube in three.js
Other 3D related articles on this blog
Look for another example from Dave C – to appear on our knowledgebase shortly
Remember the “once I got a little help” part? Well thank you to Dave Campanas (our 3D guru) for the JSON assistance, and to Michael Ha (one of our web experts) for his help getting the model into our blog. Also thanks to all who assisted via the #fme_3d channel.
Oculus photo: By Sebastian Stabinger (Own work) [CC BY 3.0], via Wikimedia Commons