Houdini Snacks | Diagonalize
Bite-sized tips, tricks, what's, and how's | #001
Much like a sketchbook, these are sporadic entries logging all sorts of discoveries while using, exploring, and occasionally crashing SideFX’s Houdini.
🢐 Houdini Version: 19.0.455 🢒
After having done a ton of geometrical work in Houdini, I hit a wall when I wanted to do a simple thing: Diagonalize a polygon’s topology. I couldn’t find many resources online, so I decided to write my own diagonalizer. Inspired by Daniel Piker’s Diagonalize node found in Grasshopper (Rhino’s parametric editor), I was able to dig out the base logic for this:
Given a mesh, turn each mesh edge into a new diagonal face.
To do this, one could (arguably) follow this logic:
- for each edge, return its respective start and end points.
- for each edge, return its connected faces.
- for each connected face, return the center.
- create a new face (prim) with the collected points [edge points, face center(s)]
Seemed simple enough…until one is left to deal with half-edges as opposed to just edges. No, half-edges are not literally half of an edge; they refer to the full edge connected to one face, therefore living on one side of the edge.
Pulled from SideFX’s documentation, take a look at this mesh. The wireframe is composed of 10 lines. But then look at the blue, directional edges. These are half-edges. A half-edge could be better described as a side edge. A given edge of a mesh, if not on a naked boundary, will typically contain 2 half edges, i.e., two edges that live on either side of the original edge. These are the blue lines in the image above.
Confusing? Probably. It took me a hot minute to digest, but eventually, it kicked. Regardless, understanding that logic, we can build a VEX to diagonalize an object, regardless of topology.
In short, I built two VEX Detail Wrangles. One provides an array reflecting the availability state of all edges (arguably, there is definitely a better way to solve for this).
The second does all the heavy lifting of diagonalizing, using the previous array to avoid creating duplicate primitives.
I won’t get into details for the code, but in short, this provides a rough foundation for diagonalizing most-any provided meshes.