Skip to content

Giving a generated character hair that can move ​

By Oleg Sidorkin, CTO and Co-Founder of Cinevva

A generated character can have a convincing hairstyle and still have no hair that can move independently. The output may be one surface, a collection of thin cards, or disconnected pieces. None of those representations tells a simulator where a strand starts, which way it grows, or how it should bend.

Our previous hair experiment began with artist-rigged avatars and a selected ponytail. This time we started with reusable hair meshes and our frog character. The question was more basic: can we fit a hairstyle, trace useful guide curves through it, and keep their roots attached during animation?

Across 46 hairstyles, the current prototype extracts 10,467 candidate guides and finds scalp connections for 10,346 of them, 98.84%. The percentage measures scalp connectivity. Motion quality still needs evaluation.

Try the mesh and its guides ​

The demo loads immediately. Choose a Hairstyle, then use Hair inspection to switch between the original mesh, mesh plus guides, and guides alone. Drag the preview to orbit, and inspect the back as well as the front. Choose an Animation to see whether the attachment follows the moving character.

Cyan curves have a scalp connection. Orange curves were rejected. "Show suggested roots" reveals the proposed attachment points. Long01 is a useful dense example. The French braid variations expose the challenge of joining separate fragments. Download the guide curves to inspect their points and attachment metadata.

Open this demo in a full window ↗

Eligible loose hairstyles now use an experimental adapter to the shared hair solver from our earlier article. It selects up to 24 guide chains, creates joints, and gives the visible mesh and guide overlay the same skinning weights. The cap stays pinned and unsupported regions remain head-bound. Short styles without eligible loose guides keep rigid attachment. Two French braid examples retain their separate experimental joint-chain treatment. Switching the inspection view preserves playback.

Fit first, then establish attachment ​

We assembled 46 CC0 hairstyle options from MakeHuman collections, dreadlock variants, and Quaternius assets. Each option has a source link in the demo, and the asset catalog and license inventory preserve provenance. Their mesh structures vary, so each needs guide extraction and attachment.

The first placement failed visibly: the hair sat behind the frog's head. Bounding-box scaling had aligned the objects without identifying the intended scalp. Our fitting pass now estimates the source crown, aligns it to the target head surface, and moves overlapping upper hair outward against an approximate head envelope.

That is similar to the separation we used in the clothing article: placing an asset, fitting its shape, attaching it to a rig, and giving it secondary motion are different jobs. A hair root should stay on the scalp, while the lengths should retain their hairstyle rather than collapse onto the body.

The frog is awkward by design: a wide head, raised eyes, and nonhuman proportions. The current upper/rear scalp mask is specific to this character, so fitting other models would require their own scalp detection. Some styles still obscure the face or have unsuitable proportions.

Trace paths through the existing surface ​

We build a connectivity graph from each hair mesh. Coincident vertices split by UV seams are welded for this analysis. The rendered source mesh is preserved. Within each connected component, we find surface paths from an initial root candidate toward separated endpoints, then smooth and resample those paths into curves.

For adjacent vertices i and j, the graph edge cost is their geometric distance:

wij=‖xj−xi‖,P∗=arg⁡minP∑(i,j)∈Pwij.

This shortest-path construction follows the mesh surface, starting from a proposed high-point root. Scalp proximity can reverse a curve later, and the path direction still needs inspection. A flat card often provides a useful path, while a closed cap or a disconnected curl is much more ambiguous.

Each candidate guide curve represents a path through the mesh. A card can depict many hairs, and the extracted path can cross their intended flow. In the guide view, check the direction of the cyan curves as well as their attachment.

Make the roots follow the actual scalp ​

A guide endpoint is matched to an eligible scalp triangle. If it is too far away, we reject the connection rather than stretch it arbitrarily to the head. Accepted roots store the triangle's vertex indices and barycentric weights.

For triangle vertices a(t), b(t), and c(t) on the animated body, the attached root is

r(t)=λaa(t)+λbb(t)+λcc(t),λa+λb+λc=1,λi≥0.

The weights stay fixed while the triangle vertices move with the skin. Parenting the entire display only to the head had left up to 0.657 mm of root drift in our sampled Walk check. Following the stored triangle attachment reduced that error to numerical precision: less than 10−12 metres for 74 sampled Long01 roots at four animation times.

This check measures root drift at the sampled times under the scene's metre convention. Hairline placement, clearance along each curve, and behavior in other animations still need inspection.

Joining disconnected fragments ​

Some hairstyles arrive as many disconnected pieces. A fragment far from the scalp may be a continuation of an already attached lock. We test both orientations and join it to an accepted guide only when the endpoints are close and their directions agree.

The current joining rule uses a 25 mm distance limit and a tangent dot product above 0.5, under this scene's scale. Only already attached paths can become parents, which avoids cycles. Curve length, point count, and joining passes are bounded. We selected these thresholds for this prototype.

Joining adds 1,851 connections to the accepted set. The French braid variation goes from 136 directly attached guides to all 509 connected, and the unkempt braid reaches 512 of 519. The remaining seven fragments stay orange. Review each join for continuity with the intended lock, because unrelated pieces can also sit close together.

Explore the measured coverage ​

Search for a style or show only those with rejected guides. The links open the corresponding live inspection view. The table contains the saved attachment audit for all 46 styles.

46 of 46 styles · saved audit

Download the complete attachment results.

All 46 styles loaded without browser errors in the audit. The extraction omitted 90 vertices across three Elvs meshes. Four focused tests check connectivity, reporting of omissions, reconstructable scalp attachments, fragment joining, and rejection of remote fragments. Desktop and 390-pixel mobile views were inspected, and the mobile page had no horizontal overflow.

The audit covers this library fitted to this frog. Broader geometry, pose, self-collision, and export testing remain open.

What has to happen before this becomes hair physics? ​

The current guides provide roots and candidate paths. A first adapter now reuses our existing fixed-step spring, rest-shape, and contact solver. On Long01 it binds 18,204 of 39,804 mesh vertices to 24 chains, and a sampled loose-hair point moved 13.6 mm relative to the head in the controlled test. The sampled movement confirms that the adapter deforms the hair. Motion quality and collision clearance still need evaluation. The mesh and overlay use the same skinning field. Reliable direction, coherent weights across each lock, and broad motion checks remain necessary.

The next steps are to review ambiguous roots and fragment joins, improve guide selection and weights without tearing across separate locks, and validate body contact during motion. Self-contact remains additional work. Export and reload must preserve those bindings too.

For generated characters, replacing a separate hair surface is a practical starting point. A fused head-and-hair mesh adds another prerequisite: identify the hair region and establish a usable scalp underneath it. Our frog experiment doesn't solve that segmentation problem.

The demo now exposes the fitted mesh, candidate paths, moving attachments, and rejected connections. The next iteration will focus on guide direction, weights, and contact during motion.