Clik here to view.

Authored by Steven Hall
This post is about an idea I had to use D3 style selections in THREE.js for constructing and updating the scene graph. D3's way of binding data to objects and doing updates using selections is a powerful paradigm for building data intensive applications. I think that power can be used to work with other kinds of tree structures outside of the DOM. To test the idea I forked D3 and put together a small selections-only library to try it out working with the scene graph in THREE.js. We'll have to keep this one in the experimental column for now, but I think it's an interesting idea.
What if you could work with WebGL and THREE.js, but could write code in the style like you see below to make this data globe?
View a live demo here
var root = SubUnit.select(scene); // hello selections var globe = root.append("mesh") .attr("material", earth) .attr("geometry", sphere); globe.node().rotation.y = Math.PI; // rotate relative to root var quakes = root.selectAll("quake") // select into the scene .data(data).enter() .append("mesh") // append a mesh for each earthquake .attr("tags", "quake") .attr("geometry", quake) .attr("material", function (d) { return getColor(d.mag); }) .each(function (d) { this.position.copy(getCoords(d.lat, d.lng)); this.lookAt(root.node().position); this.scale.z = Math.max(magScale(d.mag), 0.1); this.updateMatrix(); }) .on("click", function (event, d) { d3.select("#msg").html(d.dsc); if (this.material !== highlight) { this.material = highlight; } else { this.material = getColor(d.mag); } }); root.node().rotation.y = Math.PI; root.node().rotation.x = Math.PI / 6; // rotate everything root.node().scale.set(2.75, 2.75, 2.75); // scale the whole thing
Looks clean. If you work with D3 this is probably pretty readable. In this case there's not much happening that you couldn't do with a for loop, but you can build much more complex structures using selections. There are some important differences when using selections away from the DOM though (I'm still sorting through some of those). Getting things working took some time, but I've now got some running demos and I'm pretty pleased with the results.
If you are new to D3 and not familiar with the idea of selections, you should read Mike Bostock's great article on the idea. That will give you some context for how this could work in THREE.js.
Demos
You can see a whole assortment of other demos using the library here...
Full Set of Demos Here
I am not going to walk through the globe demo in depth but I wanted to include it here to show that there is working code. There's much more code and hands-on examples in the second article. That said, data globes are all the rage with the kids these days, so definitely checkout these demos while you're here (the code for this is in the repo).
Image may be NSFW.Clik here to view.

The Full Version is here (~7,800 clickable meshes)
Scaled down version here (1000 clickable meshes)
The full version will definitely wake up your CPU and GPU, but my Mac laptop keeps a respectable 40 frames per second.
From here, we're going to be somewhat theoretical in this article. If you want to just jump straight into it you can read the second post that takes you through some practical examples and shows some more complex code. We're going to be glossing over some details in this post because this post isn't really about details it's about an idea.
Trying Out Selections
To try out the idea of using selections in THREE.js I put together a ~600 line library called SubUnit that let's you test drive D3 style selections in THREE.js. I forked the D3 code, took just the pieces that have to do with selections and re-configured to sit on top of THREE.js and "select" into the scene graph. You can take a look at the code here...
View the code on Github
The library itself has no dependency on D3, but it's meant to be used in conjunction (like you see in the demos). The only dependency for the library is THREE.js.
Both the library and all of the demos are made up of ES6 modules. I think this makes the demos much easier to follow. The demos are using the Traceur Runtime to compile the code when the page loads. Take a look at one of the demos and view the source. The main module is in a script tag in the HTML and you see the modules and variables that are being imported at the top. While you wouldn't do this in production it makes for much easier comprehension of the demos. IMHO.
If you're not familiar with ES6 modules or the Traceur runtime compiler take a look at this intro. That's all we're doing. It's pretty simple.
Why Selections?
i'm really looking for a way to work with WebGL. My take on THREE.js is that they really want to stick to the core WebGL tasks and I think that makes sense. Out of the box THREE.js doesn't really prescribe a way to work with it. D3, I think, is different.
D3 has a way of doing things that centers around selections. To me it's what makes D3 so powerful (along with the great scales, layouts and array methods). And although D3 is (largely) used for work in 2D, there is nothing inherently 2D about a selection. It's a data structure and more. You get a smooth API for binding data to objects, making updates, setting up events, and, importantly, establishing and working in new coordinate systems. That's the key, I think - working with coordinate systems - because it's fundamental to creating complex structures in space, 2D or 3D.
Changing Coordinate Systems
To start, let's look at the way you manage the complexity of changing coordinate systems in D3. If you've only done a simple bar chart the full power of the library can easily escape you. But try working on some really sophisticated business intelligence tools and it's amazing what can be done on a single SVG element.
Think about how you create an SVG chart in D3 for a moment...
var svg = d3.select("body").append("svg") .attr("width", diameter) .attr("height", diameter) .append("g") .attr("transform", "translate(2,2)");
We set up an SVG and add a "g" element. What does that do? It's a way of "grouping" things together that also establishes a new coordinate system. From Mozilla...
The g element is a container used to group objects. Transformations applied to the g element are performed on all of its child elements.
Now when we append to that selection we are positioning relative to the "g" element's location. That's how you get things centered up nicely and makes the code easier to read and reason about. In the example above, we can call the variable "svg" and really forget about the fact that it is actually pointing to a "g" element that's been translated. The same pattern is used to create complex 3D scenes. In THREE.js you can append a 3D object (THREE.Object3D) and do the same sort of shifting between coordinate systems. In the second article we'll walk through some practical demos of this.
So, working with SVG and D3 has introduced the idea to many developers of moving from coordinate system to coordinate system and working on individual nodes and moving them relative to a container (think about placing labels, etc). It's a way of doing things that makes sense and is driven, largely, by the SVG standard that defines how these elements are to be drawn.
Which is an important point. If you think about. What is D3 good at? Well, D3 is really good at preparing an SVG document tree to be rendered by the browser. It is also great way to do the exact same thing in HTML (another tree structure with different semantics and rules). So that's how I got to this library idea. D3 is really good at preparing a tree to be sent off to be rendered. Which is precisely what you need to do with a THREE.js scene.
Let's take the changing coordinate systems idea a little further. Continuing with the D3 chart example, after setting up your SVG, you might do a number like this...
var nodes = svg.selectAll(".node") .data(data) .enter() .append("g") .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
We're now appending yet another coordinate system where we can relatively place the SVG shape and some text or whatever. And when we get to those we don't have to worry about where we are in space just place things relative to the parent node. This allows you to build much more complicated structures and it works in fundamentally the same in 2D or 3D.
If you append a circle to each node above using selections, it's just...
nodes.append("circle") .attr("r", function(d) { return d.r; });
There's no need to supply the x and y. It will be at (0,0) within the coordinate system of the "g" element. If you applied a transform to this circle you can move it relative to it's container element. And so on and so on for as deep as you want to go. Powerful stuff done with code that is easy to read and reason about. And this same way of working with selections works awesome in THREE.js as well.
Enter, Update, and Exit
One last thing to mention here, but really will have to wait to be expanded on. You're missing a lot of the power of D3 if you haven't fully come to grips with enter, update, and exit selections and how they work. This is a really fluid way of writing complex code. It is a powerful paradigm that can be used to make incredible animated displays. Although these examples don't touch on update and exit selections there is also nothing inherently 2D about this idea either.
Ok. Enough chit chat. Let's check out some examples!