Sculpting (heads and characters, Blender 5.2)
SkillDev toolsUse when sculpting in Blender through Python: sculpt a head, face or bust, a stylized or cartoon character, a creature or a realistic portrait; block out from primitives; cut planes, a jaw or gonial angle, cheekbones; fix a jaw or face that looks like a ball or balloon; stylized hair clumps; eyelids; an expression or smirk; plan remesh or multires resolution; reproduce Clay Strips, Crease, Draw Sharp, Scrape, Grab or mask moves without a tablet; final clay renders; or when a sculpt operator crashes headless.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Sculpting (heads and characters, Blender 5.2) skill
What this skill tells your AI
The instructions your AI receives, as published by scenario-labs/skills in skills/dcc/blender/scenario-blender-sculpting/SKILL.md and read by ahel’s review.
Expert sculpting is structure first and surface last: masses blocked with stated planes and corners, proportions locked at low resolution, every stage judged by eye through a long lens, and appeal as the final test, not the mesh numbers. The agent builds blockout and primary forms headless (scripts/bx_sculpt.py: smooth-blend Clay, plane cuts, numpy brushes) and does client-quality surface work with Blender's real brushes in a live GUI session (bx_gui). If a sibling skill named here is missing from your available skills, ask the user to install it (npx skills add scenario-labs/skills --skill <name>); unattended, proceed from tool schemas and flag the gap.
REQUIRED BACKGROUND: scenario-blender-expert (execution channel, review loop, 5.2 API changes).
Stance (the expert delta)
- Planes are stated, not found. Thelen cuts plane borders with Draw Sharp and re-cuts them whenever a face "looks off"; Naydenov simplifies into planes, then smooths; Reinhardt uses Scrape, Trim and Line Project for clean cuts. Executable form: give the plane (point + normal) to
Clayhalf-space clips orplane_cut/corner_cut. Aflattenorscrapedab fits its plane to the ball under it, so it follows the ball. - The jaw is a block with a gonial corner, the cheekbone a mass with its own lower plane. Zarins: the gonial angle is the age and sex dial, steep in adult males; the widest face point is the top of the zygomatic arch. Naydenov: the cheekbone runs from the ear down and forward, only its lower edge shows. Thelen: bone plus tissue, never razor sharp.
- Fix mass upstream; planes only restate. If re-cutting planes does not fix the look, the problem is mass or proportion (Thelen's diagnostic). Measured: plane cuts on a balloon jaw flipped the form metric but rendered as a gem facet; rebuilding the jaw block fixed it.
- Low resolution as long as possible. Abbitt: smoothing is strong only on big polygons; Thelen: lock proportions coarse. Symmetrize after every remesh (Keelan Jon), then a global relax (Kaspar FDscc66fC90 00:11:55).
- Indicate small landmarks early (nostrils, brows, eyes): Yan found a too-wide nose from the nostrils (vB7kPWjBgQI 00:05:11).
- Stylize by consistent exaggeration (Yan: pick it in minute one, make neighbors follow; a long face needs a smaller skull, not a stretch).
- A concept head needs its cues. Thelen: hair makes a male head read better (00:48:58); Naydenov: hair changes the read a lot (00:53:05). An "adventurer" with no hair or costume reads as a bald mannequin.
- Asymmetry and expression live on a shape key; the basis stays neutral and symmetric (Kaspar f-mx-Jfx9lA 00:09:44; Thelen 00:38:27). Expression tests expose proportion errors; fix them in the neutral (Kaspar 00:10:49).
Establish first
| Input | Changes | Default when silent |
|---|---|---|
| Who (sex, age, type, attitude) | gonial angle, brow, jaw width, shape language | adult male, neutral basis, stated [added] |
| Style | stylized: exaggeration table; realistic: canon + reference | stylized, "abstracted enough to not be uncanny" (Kaspar) |
| Character cues | hair, costume, props that sell the type | at least hair plus one costume signifier [added] |
| Purpose | still (vertex paint, decimate) vs game or film (retopology) | still; scenario-blender-retopology if animated |
| Delivery framing | detail frequency, expression size | bust fills a 1080 px frame [added] |
| Scale | nothing if sizes are fractions of head height H | H = 0.24 m [added] |
| Channel | headless numpy / Clay, or live GUI brushes | headless blockout; GUI for surface when the bridge is up |
Workflow
- Design table.
G = S.head_guides(H), a STYLE dict (the one or two exaggerations), the cue list, and the landmark points of the planes: gonion, chin bottom, cheekbone. GATE: written down. - Blockout (voxel H/40). Default for heads:
Clay. Cranium ellipsoid clipped by skull side and front-taper half-spaces; a jawsd_round_boxBEHIND the mouth mound, clipped by side, underside and ramus planes through the gonion; a square chin block; cheekbone ellipsoids along the ear-to-cheek line with a lower plane; mouth mound; brow ridges; nose; neck leaning about 15 degrees; ears; frontal box around the eyes. Blend big masses at 0.08 to 0.15 H, clip edges at 0.02 to 0.03 H. Option:union_remeshof primitives (rounded_box is a Catmull-Clark blob that reads as a ball: never use it for a jaw). GATE: 1 component;lower_face_report(head, H)["ball"]False; silhouette plus 90 mm renders show a jawline and gonial corner in profile and three-quarter; the exaggeration visible. - Primary forms (H/100 to H/110). Rebuild the Clay at the finer voxel with landmarks: sockets (sphere 1.1 x eyeball, smaller than the lids), thin shell lids around separate eyeballs (Keelan Jon's lids from the eyeball, amVAlpxHp8k 00:37:05), nose wings tucked in, ear bowls, neck muscles. Hair and costume as separate Clay objects (
to_object(name, symmetric=False)for anything asymmetric). GATE: profile beats; eyes not marbles or bags; hair frames the face;stage_reportclean. - Secondary (H/130 to H/150,
remesh_stage). Lines withcrease_line(mouth, under-lip, lid rim) on surfaces facing the projection; nostrils from below. Restate planes withcorner_cut/plane_cutonly where the mass is right and moves stay small. GATE: under 100k faces (Abbitt), no scratches, cracks or rims in 90 mm renders. - Surface finish (client quality): live GUI. Real Clay Strips, Scrape, Crease Polish, Smooth 0.2 via
bx_gui(fixed and verified: strokes raycast onto the mesh and pass object-space locations;set_view(frame=obj)first,view_distancea few head heights). Headless numpy strokes suit blockout and primary forms, not polish. Multires only on a settled clean base (Henning Cmi0KoFtc-4 00:16:04). - Expression. Neutral symmetric basis;
sc = S.Sculptor(head, symmetry_x=False),move_featurethe corner, cheek, lower lid, opposite brow;S.write_shape_key(head, "Smirk", sc.co). Size the corner move to the delivery framing (Numbers). Voxel remesh drops keys: last step. - Final render.
S.final_render(objs, path, direction, lens=90, res=1600)(cavity, framed on real vertices) from front, profile, three-quarter, neutral and expression; open every image.
Inside every stage: render, name ONE weakest link, fix it, re-render (Yan). A metric that passes while the render looks wrong means the render wins.
Numbers
| Value | Number | Source |
|---|---|---|
| Voxel ladder | H/40 blockout, H/65 to H/110 primary, H/130 to H/235 secondary, about H/330 detail | Morren, Abbitt; example |
| Faces from voxel | about 1.5 x area / voxel^2 (voxel_for_faces) | measured, 3 % |
| Example bust faces | H/40 8k, H/110 64k, H/150 103k (with neck) | measured |
| Face gates | shape before 100k; detail about 500k | Abbitt |
| Raw remesh mirror error | max 0.67 to 0.75 voxel, mean 0.05 to 0.07 voxel (nearest vertex) | measured |
| Clay blends (head) | masses 0.08 to 0.15 H, plane clips 0.02 to 0.03 H, lids 0.012 H | example [added] |
| Jaw | bigonial 0.90 to 1.00 x bizygomatic (example 0.93); ramus-to-base angle 124 degrees in the example | Thelen; example [added] |
| Eyes (stylized) | radius 0.064 H, lids 0.012 H thick, upper margin 21 degrees above center | example; 14 degrees read sleepy |
| Hair | clumps 0.065 to 0.115 H radius, rising 0.8 x radius, from the hairline back; base 0.008 to 0.02 H | example [added] |
| Corner move that reads | about 1/8 of mouth width (8 mm on 65 mm, 0.03 H); invisible at 1/30 | measured |
| Pixels per mm | bust fills 1080 px: 2.8; bust 270 px tall: 0.75 | measured (framing) |
| Smooth strength | 0.2 (5.2 default 0.7) | Henning |
| Crease resolution | at least 3 to 4 vertices across the radius | Ryan King |
| Review lens | 85 to 95 mm perspective | Morren, Kaspar, Naydenov, Yan |
| Landmarks | eye line 0.5 H; nose bottom halfway brow to chin; lip parting 1/3 nose to chin; ear nose base to brow; width H/1.5; mouth corners under eye centers; canthal tilt about 8 degrees; neck about 15 degrees forward | Abbitt, Naydenov, Thelen |
Quality gates
- Measurable:
S.stage_report(obj, voxel)(components 1, non_manifold 0, stretch p95/median under 2.5, mirror_max under 1e-4 before asymmetry).S.lower_face_report(head, H):ballTrue means the lower face fits one sphere within 10 % and twice as well as a plane (calibrated: the three E2 balloon jaws 0.057 to 0.082, the baseline 0.18 to 0.20, the v2 example 0.23 to 0.26).S.profile_rhythm(obj): chin out, in, lips out, in, nose out (a nose hanging below the nose base hides the lip beats).sc.planarity(c, r)for a stated plane. - Visual (the gate):
S.long_lens_renderorfinal_renderat 85 to 95 mm from front, profile, three-quarter and below, plusbx_review.review(..., modes=("silhouette", "matcap"))for the ortho silhouette. Order: silhouette, big planes (cavity off, ormode="flat"), below and above, lines, character read at thumbnail size. Rubric:references/critique.md.
Common mistakes
| Mistake | What it looks like | Fix |
|---|---|---|
| rounded_box or ellipsoid jaw, heavy smoothing | balloon lower face: cheek, jaw, jowl one sphere | Clay jaw block with stated planes; lower_face_report gate |
| Flatten or scrape dabs to "make planes" | facets that follow the ball | stated planes: Clay clips, plane_cut, corner_cut |
| Plane cuts on a wrong mass | gem facet with a rim, metric passes | move or rebuild the mass first, then cut |
| Jaw block with its front ahead of the mouth | a mask or slab over the lower face | jaw behind the mound; front belongs to mound and chin |
| Tall jaw block, small blend | a panel edge across the cheek | low block, 0.15 H blend upward |
| Socket wider than the lids | ring groove, eye bags | socket 1.1 x eyeball, lid blend 0.012 H |
| Lids reaching behind the eye equator | sealed pocket, 3 components | clip lids at the eye center plane |
| Uniform hair offset, or clumps on a thick cap | helmet ledge, beanie with worms | thin base, clumps make the volume |
| Clumps starting behind the hairline | bare headband over the forehead | start clumps at the hairline |
| Symmetrizing asymmetric parts | swept hair mirrored, center seam | to_object(..., symmetric=False) |
| Crease projected across a grazing surface | parallel cracks | crease only surfaces facing the view; skip it |
| Smile sculpted into the basis | asymmetry cannot be removed | neutral basis, write_shape_key |
| Corner moved 1 to 2 mm | expression invisible | about 1/8 of mouth width, check pixels |
| No hair or costume | bald mannequin | cue list in stage 0 |
| Detail before proportions | lines on a wrong skull | stay coarse until the gates pass |
| Stroke snapped with nearest from far away | groove on the nose tip | on_surface(p, view) |
| Mask survived the remesh | a region refuses every brush | remesh_stage clears it |
| GUI strokes with the view zoomed out | whole mesh flattened | bx_gui.set_view(frame=obj), check view_distance |
| Hairline as one tilted cut | a garrison cap from the side, vertical wall at the front | hairline as a function of azimuth (sideburn, over the ear, down to the nape), quiff ramp from the hairline over about 0.12 H [eval] |
| Mirrored eyes | no gaze, a staring or blank attitude | two aimed eyeballs; lid margin and brow angle are attitude dials (level brows for a neutral basis) [eval] |
| Feature attached at two points | a nose that floats in profile, see-through gaps | ray-grid silhouette-hole probe per view; give a big nose a side wall to the cheek; bx_audit self-intersections after the last remesh [eval] |
Blender 5.2 notes
- Headless CRASH (segfault):
sculpt.symmetrize,sculpt.mesh_filter,paint.mask_flood_fill,sculpt.mask_filter,sculpt.face_sets_create,sculpt.face_sets_init,object.voxel_remeshin Sculpt Mode. Poll fails:sculpt.brush_stroke,sculpt.set_pivot_position,sculpt.detail_flood_fill, trim gestures. Work:paint_mask_extract,brush.asset_activate, Edit Modemesh.symmetrize,quadriflow_remesh, multires ops. - OpenVDB ships with Blender 5.2 (
import openvdb):FloatGrid.copyFromArray+convertToQuadsmesh the Clay. - Brushes are Essentials assets; Flatten, Fill, Scrape are one Plane type;
sizeis a diameter; Draw Sharp defaults to SUBTRACT.sculpt_toolissculpt_brush_type. - Voxel remesh output is flat shaded (
shade_smooth()), keeps attributes (mask included), drops shape keys. - NumPy 2 in Blender:
np.ptp(a), nota.ptp().
References
references/procedures.md: tested code for every stage (Clay recipe, planes, form check, hair, lids, expression, final render, crash matrix, brush table, GUI recipe); load before writing any sculpt script.references/expert-notes.md: principles by expert with timestamps; load when designing a character or choosing methods.references/critique.md: stage rubric with blockers; load at every gate.references/sources.md: the 27 source videos with best timestamps.- Example:
tests/code/blender-sculpting/stylized_head_blockout.py(13 s, renders instylized_head/stage_N/); comparison:tests/code/blender-sculpting/compare/compare_sheet.png.
Signals
- GitHub stars
- 681
- Forks
- 82
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
scenario-blender-sculpting- Source
- github.com/scenario-labs/skills