Several months ago I supervised a project called Speak and May the Plague Take You. This short film required some surrealistic imagery of giant clocks smashing into the ground, including an hourglass. After wrapping the project, I wrote this technical breakdown because I tend to forget everything. Since glass shattering is a somewhat common effect but not necessarily simple to achieve, I hope this breakdown will help other Houdini artists grasp the fundamentals and maybe save some time.
The hourglass shattering effect required a lot of exploration in Houdini DOP’s. The sidefx glass of water shattering tutorial (I hesitate to call it a tutorial) as well as the example files for the voronoi fracture OTL were helpful in giving me a starting point to build my effect.
After a month of R&D I had the following workflow figured out:
I used the voronoi fracture OTL to create a dynamic fracture simulation where the hourglass drops and is fractured automatically (and fractured even more when the glass collides with geometry). I then took the fractured glass geometry and used it as a collision object for a particlefluid sand simulation.
The fracturing geometry, however, created a problem for the particlefluid solver for the sand. Because the glass geometry was being fractured dynamically (even though it was cached out in a bgeo sequence) the point counts would change and the particlefluid solver would freak out. This seems to be a common issue with the dynamic fracture tool, as people from SideFX effectivly said “yeah, we know, sorry”. It seemed like I would have to pre-fracture the geometry.
I really liked the look that the dynamic fracture gave so I was hell bent on finding a way to use it. Getting it to work required some ugly trickery. I first identified all of the frames in which the voronoi sop had performed a new shatter. Thankfully, there were only four or five. Then, I divided up my cached bgeo sequence into different sets of frames respective of the fracture points. I had a sequence that went from 1 to frame 316, for example. On frame 317, the geometry fractured for the first time, and so that bgeo set went from 317-358, when another fracture took place. For this and each subsequent set of frames, I duplicated the first frame in the set for how ever many frames were missing, starting at 1. So if the set went from 317-358, I took frame 317 and duplicated it so that single bgeo file was used for frames 1-316 in that set. This way I had a set that went from 1-358, but with frame 317 as the ‘starting’ point.
By doing this, I ended up with a series of bgeo sequences that was consistently the same point count and never fractured beyond its initial configuration. It is now possible to take these sets of geometry into the particle fluid simulation and ‘trick’ Houdini into accepting it.
Unfortunately, it wasn’t enough to just use a switch DOP (which I found to be incredibly buggy to begin with) on the glass geometry, as the particlefluid solver would still freak out. To get this to work, I had to actually write out the particlefluid sequence to one of my pre-determined fracture frames, say 1-316, and then re-import the last particlefluid cache frame as a particlefield and set the particlefluidobject to use the that field as its initial state on a new simulation with the next set of fractured collision geometry. So, instead of performing one simulation for the sand, I had to perform a simulation for
every set of fractured geometry, using the last frame sim’d as a starting point for the particle fluid.
1) DOP simulation of glass shatter using voronoi fracture OTL written to a bgeo sequence
2) Separate out the sequence into sets respective to frames where fracturing takes place
3) Duplicate first frame of each set so the set starts at 1 (instead of 317, for example).
4) Simulate particlefluid using the different sets. Stop the simulation the frame before a fracture occurs, re-import the last frame you simulated, use it as an initial state with the next set of collision geometry.
You’d think that it would be possible to do this without separating out the fractured collision geometry (if you just stopped the simulation before a fracture occurred in the collision geometry and set an initial state from the last frame) but I found it to be necessary in order for Houdini not to crash. Perhaps someone else can get that working.
FRACTURING THE GLASS
The DOP simulation used for the voronoi fracture is based on one of their example files, stripped down a little and simplified. Seperate RBD objects are brought in, one for the glass (which is run through the jl_fracturedpieces) and two others for the wood and metal connector of the houglass.
The simulation generally performed as expected. I found that fractured pieces created by the voronoi fracture tool weren’t getting much gravity applied to them respective of the original geometry, so I created an additional gravity field that only affected objects named rbdobject1_piece*. This allowed a fine degree of control over the look and scale of the simulation, eg how much the pieces would float out before being brought down by gravity (useful for making everything look larger). Setting the various densities on the RBD objects also gave it a more realistic interaction, eg glass was 25 and the wood was 2000.
Additionally, I found that the glass pieces were passing through the portions of the wood structure that were thinner, such as the dowel rods in the mid section of the structure. I found that increasing the Ray Intersect Divisions on the RBD object for the wood structure to 90 90 90 solved this problem (turning on Show Collision Geo is useful here).
The initial sand geometry was created by subdividing a box. The actual amount of particles wasn’t determined by the subdividion level, it was determined by a parameter called “particle separation”, but I found having a liberal subdivision level was useful for starting out. At this point I also brought in all of my separated bgeo sequences via file sops.
The simulation itself is based on the shattering glass example from Sidefx. It’s actually fairly simple once you figure out how to work with the collision geometry. In the screenshot to the left, you can see by which set of collision geometry I have connected that I’m starting at frame 362. The particlefluidobject would be set to start at frame 362 using 361 of the particlefluid simulation as an initial state.
To write out the fluid sim, I used a DopImport with an object mask of: `dopobjscreatedby(“/obj/FluidSim/particlefluidobject1”)` set to “Fetch Geometry from Dop Network”.
BRINGING EVERYTHING TOGETHER
When bringing back in the hourglass geometry simulation, I applied the materials using group nodes I had created prior to the dynamic fracture simulation. For some reason, I had to lay down a transform sop at the end of the tree for the materials to show up correctly.
Bringing in the cached particlefluid sequence is a little more involved. I decided to go with metaballs for the sand, and ended up having to set the metaball radius fairly low (0.8) in order to get something that wasn’t incredibly clumpy (it was still clumpy, ultimately another method is probably better).
Applying metaballs to particles is fairly simple and involves only a copy node at the core. I found that I had a lot of excess particles that streamed out everywhere (out of the field of view) that were basically lower than the threshold of the metaball, so they were effectively invisible. However, it took an incredibly long time to calculate the metaball to poly conversion with all of these excess particles. Using a group node to group together particles within the area of a sphere and then deleting the excess particles saved me days of simulation time. This can all be done within the group node and then appending a delete node that deletes the group’s inverted selection.
Once I had written out polygons from the metaballs, I applied the sand material (a simple UV projection) and faceted the polygons.
GLASS REFRACTION AND CAMERA PROJECTION
I spent a lot of time trying to figure out how to pass an alpha through the VEX glass material. Basically, I realized it couldn’t be done by the nature of refraction. Once I accepted that I would have to lock in the position and animation of the hourglass in Houdini rather than in compositing, I went about figuring out how to get the background refracting through the glass.
Simply applying a viewport or camera background doesn’t affect refractions. A relatively simple method is to take a grid object, position it roughly so that it covers the entire field of view for the course of the shot, and then project UV’s from the camera onto the plane. This is done via a UVTexture node set to “Perspective from Camera” and pointed to the respective camera. You can then apply a material that has the image sequence as the color.
Good settings to use for materials that need to be self illuminating, such as the image sequence background, are (in a VEX Supermaterial) a diffuse of 4 and a transmit of 1. Everything else should be zero. The image sequence is applied in the diffuse channel. Of course, the alpha for the grid should be turned on or off depending on the needs of the shot. If it’s set to Phantom renderable than it will still refract through the glass but won’t show up outside of the glass.