Right then… now it’s time for the really fun stuff. Looking back over this series of posts, we introduced it then looked at adding simple geometry to the Forge viewer, followed by animated skeletons and animated skeletons with fixed meshes attached.
Today we’ll dig into making our animated skeletons properly visible. Having given up on using a SkinnedMesh, the remaining option was to tweak the underlying display of the SkeletonHelper object. This proved challenging for all sorts of reasons. Back in Chrome 55, it seems the ability to show lines with widths broke in three.js. This was fixed in three.js r91 or r92, which doesn’t help users of the Forge viewer, who are currently using r71. So we can’t just go in and tweak the linewidth setting of the SkeletonHelper’s material, as it won’t change anything.
Luckily for us, there’s the MeshLine library, which helps build a mesh to represent a thick line. I wasn’t aware of this awesome library until Elias Cohenca from the BIM 360 viewer team pointed me at it during an internal discussion. Elias has even forked the library to make a version that works well with the r71 (and consequently the Forge viewer). Too cool!
Elias suggested copying the implementation of the standard SkeletonHelper object and updating it to extend a Mesh – managed by an underlying MeshLine – rather than extending a LineSegments object, as it does in r71. I went ahead and did this, but quickly found that having a single MeshLine doesn’t work for representing skeletal geometry: it’s great for geometry with contiguous segments – such as a flowline, something we’ll see in a future post – but it doesn’t work with pairs of vertices that represent disconnected segments.
This left me with two choices: either to tweak the shader implementation to pick up pairs of vertices – rather than treating them as connected segments – or to store a series of MeshLines, one for each bone, and then use these to generate multiple Mesh objects. I’m not a hardcore HLSL coder, so opted for the latter choice, leaving the shader modification path open in case the performance wasn’t adequate. (This might well be the case if dealing with huge crowds of skeletons, but I doubt we’ll be working with so many for some time to come.)
So rather than having the new SkeletonHelper2 object extend a Mesh, I switched to have it extend a Group (which is basically a THREE.Object3D that brings a bit of syntactic clarity to the fact it contains multiple objects, in turn).
I’m really happy with the results… having separate meshes also makes it easier to manage colours, having a different one for each bone.
One major improvement came when – at Simon Breslav’s suggestion, as he’d come across this when animating robots inside the Forge viewer – I set the MeshLines’ materials to have depthTest set to false. This means the skeletons will be visible through walls, but frankly that’s actually a feature, rather than a bug: it’ll be very useful for people trying to work out where (for instance) the bridge is inside Pier 9, once we can visualise bodies walking across it.
Here’s the TypeScript code for the SkeletonHelper2 class:
Here’s the updated extension implementation:
That’s it for this series on animating skeletons inside the Forge viewer. At some point I’ll be hooking this up to movement data derived from video footage, which will be really cool. I’ll share news about its integration into Dasher 360, as it happens.
In the meantime I’ll share some information on other uses we’ve found for the MeshLine class, to implement something we call Streamlines (or Speedlines, in a more extreme case). I think this is going to be super-interesting to anyone looking to display simulation and analysis results in the Forge viewer (I’m thinking CFD results, in particular, but that’s just one obvious example).