force_table_of_contents #
This node captures nearby sparse guides and deforms a set of dense curves based on the way those guides have been modified. Nearby guides are selected based on criteria such as hair-guide alignment and similar lengths, up to a limit.
Outputs #
This node produces two outputs:
- Deformed curves.
- Curves that could not find any capture weights, and thus could not be deformed. You can then either leave them out from the output to delete them or deform them in some other manner. These curves can be optionally included in the output as a skin deformation, which is suitable for short hair.
Workflow #
The general workflow for working with this curve deformation system is:
- Load a dense groom. This may or may not come from Houdini.
- Use the hair_prepare node to transfer necessary skin attachment attributes to each primitive.
- Use hair_select or hair_extract_clumps to select simulation guides from the set of dense curves, or import existing guides and use hair_prepare to similarly prepare the guides for mesh attachment.
- Simulate or otherwise deform the guides (a procedural application of hair_collision may be sufficient).
- Use this node (hair_deform) to associate guides with each curve of the dense set and deform them to the animated guides.
- Use hair_collision to push any guided curves out of the collision shapes in a post sim operation, if necessary.
- Profit.
Capture #
Finds nearby guides to build a weighted deformation spline. The resulting deformation spline will be a weighted composite of the animation on the captured guides.
Capture Criteria #
Many guides are considered as a deformer and the nearest few that meet the following criteria will be used:
- Search Radius Scale: A scale on the guide search radius. Can help dial in the right capture weighting for calculated guide search radius.
- Minimum Guide Alignment: An alignment vector is established by building vectors between the root and tip of the two curves, then comparing the angle between them. The angle must be lower than the provided number of radians to be considered as a guide. This is the maximum number of radians allowed between a guide and a curve. A value of 0 requires the curve and guide to be perfectly aligned. A value of
$PI/2will allow a 180 degree angle (90 degrees on either side) between the guide and curve. - Minimum Length Ratio: Guides must be at least as long as this ratio to be considered. We do not want very short guides to drive the deformation of a long curve, since the tip of a curve could be inappropriately deformed by small guides. The ratio is calculated by multiplying the curve length by this ratio, then comparing the prospective guide to that value.
- Maximum Length Ratio: (Optional) Guides must not be longer than this ratio to be considered. This is optional, since typically a longer guide can still adequately deform a shorter curve. However, since long guides may interact with different colliders, we may want to select only guides that are closer to the curve length.
Capture Radius #
The guide capture radius may be explicitly set or it may be calculated. If the capture radius is calculated, it will be determined based on the distance between nearby guides. This means that tighter guide distribution will have a smaller search radius. This may be beneficial so that localized densities may be used to determine guide weighting.
Capture Iterations #
We begin with the most aggressive capture criteria, but that will often result in many curves uncaptured.
We iteratively capture guides with more and more permissive critera to give ourselves the best possible chance of finding good guides, while still reducing the chances of leaving uncaptured guides.
Existing Capture Attributes #
You can ignore the capture process entirely, if each curve primitive has a guides int array and a weights.
The guides array contains the primitive numbers of the guides on the guide geometry. This means that the guide geometry topology must remain consistent to when the array was initially created. Since this is based on primitive numbers (not id), you cannot build a guides array and then use hair_select, without fixing the guide selection values after selection.
Deformation #
Given a weighted deformation spline, use the curve’s parametric u value to determine an appropriate offset.
Guide Extrapolation #
Captured guides that are shorter than the curve will be extrapolated to the full curve length, which allows for a smooth and natural feel even with less-than-ideal guides.
Guides can be extrapolated linearly or polynomially, which will continue the curvature at the tip.
Redistribute Detail changes how a short guide fills the extra length. By default the guide keeps its shape and a smooth section is added past the tip, so any waves or kinks stay bunched in the original length. With this on, that detail is spread across the whole extended length instead: the guide is split into a broad shape (which still follows the guide and its tip extension) and the detail riding on it, and the detail is stretched to cover the full length. It only has an effect when a guide is shorter than the curve, and guides with no real detail are left as they are.
Smoothing Iterations and Strength set the split between broad shape and detail. More iterations or higher strength treat more of the guide as detail to spread; lighter values stay close to the plain extension. They default to 24 and 0.4.
Styles and Guide Attributes #
Styles #
A groom normally has a single rest shape. Styles let you store alternate rest shapes on the groom, such as a wet or a frizzy version, and blend the hair toward them per region using masks the guides carry.
Name the alternate shape attributes in Style Attributes and the guide masks that drive them in Style Masks. The two lists are paired one to one by position: the first style is driven by the first mask, the second by the second, and so on. The names are arbitrary and the pairing is entirely positional, so Style Attributes wet frizzy with Style Masks style_mask frizzy_mask blends the wet shape by style_mask and the frizzy shape by frizzy_mask.
Each mask is composited from the guides onto the groom like any other attribute, so you do not need to list it under Guide Attributes as well. The composited mask then blends the groom’s rest shape toward the style before anything deforms. Because the blend happens on the rest shape, the styled hair is deformed by the guides in a single pass with no change to the displacement itself. Where a mask reads zero the base shape is kept exactly; where it reads one the strand takes that style’s shape fully; in between it blends. If several masks overlap and sum past one they are scaled down together, so the result never overshoots a style. A style named without a matching shape on the groom is skipped.
Style Mask Extrapolation Mode sets how a mask is read where its guide is shorter than the strand, the same set of choices the composite attributes offer. Normalize remaps the guide’s whole mask onto the full strand, Hold clamps to the guide-tip value, and Linear or Polynomial continue the tip gradient, with Polynomial decaying the added curvature by the extrapolation decay. The one setting drives both the shape blend and the written mask value, so the two stay in step. It defaults to Normalize, which keeps a painted mask following the hair proportionally.
Guide Attribute Transfer #
Any point int, float, vector, or vector4 attribute the guides hold can be composited across the captured guides the same way the deformation spline is, then written onto every deformed curve. This is how a mask, width, color, id, or normal painted on the guides can ride through to the dense hair.
List the attribute names in Guide Attributes, separated by spaces. The values are read from the animated guides, so you get their deformed value rather than a rest snapshot. Anything you leave off the list is untouched on the groom, and an attribute whose name already exists on the groom is overwritten, which is exactly what lets a guide mask land back on the hair under its own name.
Where a captured guide is shorter than the curve, the attribute has to be carried past the guide tip, and there are three ways to do it, matching the guide position extrapolation above:
- By default, the attribute is normalized: its whole root-to-tip profile is remapped onto the full strand, so the guide’s tip value always lands on the real tip.
- Names listed in Guide Extrapolate Attributes continue the gradient the attribute had at the tip instead, extending values linearly.
- Names listed in Guide Hold Attributes clamp to the tip value and stop changing past it, which suits ids or region tags that should not drift.
Within the length a guide actually covers, all three read identically; the mode only matters past a short guide’s tip. Integer attributes round on write, normals are kept unit length, and quaternions stay normalized. Each attribute keeps its type info as well, so a color, normal, point, quaternion, texture coordinate, or vector lands on the groom as that same kind and transforms correctly downstream instead of falling back to a plain vector.
Displacement #
Displacement Modes #
The displacement mode combo offers three choices: Translate, Swing (Slide), and Swing (Pinned). All read the same blended per-curve guide; they differ in how a strand follows it.
Translate #
Each strand keeps its rest shape and is simply moved to follow its guide. However far the guide has shifted from its rest pose to the animated pose, every point on the attached strands is pushed by that same amount, like picking up the hair and setting it down wherever the guide went.
Because the strands only slide with the guide, they do not reorient when the guide bends or twists; they hold their rest orientation, and the clump is kept from stretching or collapsing by the distance constraints. This looks great when the guide motion is mostly drift or sway, and less convincing when the guide bends or curls sharply, since the strands will not rotate to follow that bend.
Swing #
Each strand rides on the guide as if pinned to a frame that bends and spins along with it. As the guide curves or twists from its rest pose into the animated pose, the strand swings and rotates to match, the way clumped hair naturally pivots around the strand it is following.
Instead of just relocating the hair, this preserves the strand’s shape relative to the guide, so curling, bending, and twisting guides all read cleanly.
Swing offers two ways to anchor each point along its guide:
- Slide: points slide freely along the guide so the strand holds its rest length through a bend. This is the right choice for straight or gently bending guides, where keeping exact length matters most.
- Pinned: each point is pinned to a fixed fraction of the guide and never slides, so the motion stays clean on tight curls. The strand’s length then follows the bend rather than being held exactly. Prefer this on curly guides, where a sliding point tends to read as noise crawling down the strand.
Curve Processing #
Curves may change length after the raw offsets are applied, so we also forcibly trim/extend the curves to their original length.
Guide Tightening will attempt to keep a stable distance of the curves to the guides through deformation.
Twist #
If twist is enabled, curves will rotate around the guide at the number of radians, interpolated along its length.
If the guide is shorter than the curve, the twist can be extrapolated, held,or normalized to the full length of the extrapolated guide.
Guide Tightening #
After deformation, it is often the case that a clump shape will splay out, especially if the surface skin has bent relative to its neighbors.
Guide Tightening will pull deformed curves back to its relative distance from the guide, if it is further away from its distance at rest.
Note that this only applies to curves that end up further away from their distance at rest. If the curve is inside the target distance, it will be left as it is.
Velocity #
Transfers velocity and acceleration from the animated guides to the deformed curve points in a single pass. The pass runs unconditionally and requires v on the incoming guides; accel is an optional value-add that enables the acceleration output and a more accurate reconstruction (see Source Attributes).
Source Attributes #
Velocity is computed upstream on the animated guide points before they enter the guide deformer. Use a Trail SOP on the anim guide curves. Setting it to “Compute Velocity and Acceleration” is recommended: the added accel lets the transfer use that mode’s centered differencing to reconstruct the neighboring frames it reads the guide’s rotation from, and emits an acceleration output. With velocity only it falls back to a backward-difference reconstruction (off by about half a frame) and writes no accel.
| Attribute | Type | Required | Description |
|---|---|---|---|
v |
vector | yes | Point velocity from guide animation |
accel |
vector | no | Point acceleration from guide animation |
twist_rate |
float | no | Twist angular velocity in radians per second |
The incoming guide v and accel should have “vector” type info (the Trail SOP sets this by default). The node tags its own output v and accel as “vector” automatically, so the downstream transformbyattrib rotates them from rest into anim space.
v is required: if it is absent the velocity pass is skipped entirely. accel and twist_rate are optional value-adds, disabled automatically when missing — without accel the pass uses a velocity-only reconstruction and writes no acceleration; without twist_rate the twist-rate contribution is dropped.
Method #
In a single pass, each point is transported rigidly about its guide pivot. The angular velocity and angular acceleration are measured from how the guide tangent rotates between reconstructed neighboring frames, so the velocity swing follows the same geometry as the position deform.
Because it transports rigidly about the guide, it does not capture the small tangential sliding introduced by the resample redistribution or the target-space constraint; for hair those residuals lie mostly along the strand, the least visible direction for motion blur.
Computing Twist Rate #
No built-in Houdini node computes twist rate. Use a wrangle with a Time Shift on the second input:
- Input 0: current frame anim guides (with
twist) - Input 1: previous frame anim guides (Time Shift, frame - 1)
float tw_cur = f@twist;
float tw_prev = float(point(1, "twist", @ptnum));
f@twist_rate = (tw_cur - tw_prev) * @TimeInc;Troubleshooting #
Debug Mode #
Curve deformation can often be difficult to diagnose.
Setting Debug allows users to select specific curve ids.
Selected curves will show their captured guides in a dimmer color, both in their rest (blue) and deformed (red) positions.
Using the selection button allows selection by curve id.
The main issues to consider when troubleshooting are:
- Deformed curves are penetrating collision surfaces: Use hair_collision to bump the hair back into position.
- Curves are being deformed by inappropriate guides: Consider making the capture criteria more stringent, and increase the number of iterations. Alternatively, select more guides. Oftentimes, more guides are necessary around collision surfaces, such as a shirt collar.
- Guides are clearly identifiable in the clumping: Increase the maximum number of used guides.
- Deformation is too mushy: Decrease the maximum number of used guides, to get more discrete deformation.