pipelines/CRAFT_RIGGING_PIPELINE.md
CANON SUBORDINATION — this document is PROPOSAL-TIER: it serves canon and never outranks it.
Canon served: the CVD's AAA direction and THE JOSH GATE (the Prologue→Ch 13 slice must render
a protagonist that survives a sighted read); the defect board at
build/3d/best_a14/records/ROUTE_A_RESIDUALS.md (OPEN-0 … OPEN-7), which is the standing work
order this document exists to serve.
If this document disagrees with canon, CANON WINS and this document is the defect.
Tier: RESEARCH SYNTHESIS, proposal-tier. It contains no canon and rules on nothing. Every
claim about published practice is cited to a URL, or to a book/paper by full title and author.
Every claim about our own stack is cited to a file and, where the file is long, to the function,
the flag or the JSON field. Claims are labelled CRAFT CONSENSUS where practitioners agree
without anyone having measured, and EVIDENCE where somebody measured something and published
the number. The two are not interchangeable and this document does not dress one as the other.
§6 is the citation audit — an independent re-fetch of the sources, the repairs it forced, and
the claims that are marked unverified-at-source as a result. Read it before quoting §2 onward.
Scope. Binding and weight solving; the influence budget; the unit/scale contract and the
cm-scale trap class; skeleton, bind pose and retarget; the pre-ship skeletal-mesh checklist;
automated character validation; and the deformation layers that sit above linear blend skinning.
Out of scope: facial rigging and FACS (owned by PIPE_CHARACTER_MODELS_2026-08-06.md §5), motion
synthesis and retarget *sources* (owned by PIPE_ANIMATION_2026-07-29.md), and cloth simulation.
---
Our rig lane is not short of instruments. It is short of a *published bar* to point them at. The
evidence for that is on our own board, in Josh's words, at
build/3d/best_a14/records/ROUTE_A_RESIDUALS.md OPEN-0: every gate went green — ROM no-shatter,
likeness deltas under the C4 floor, the scale mechanism proven two ways — and the figure was graded
down on sight. The board's own diagnosis is the right one: **every instrument we own measures
PRESERVATION**, and preservation is not quality.
Read off the artifacts rather than remembered, here is what the current bind actually is.
geodesic_bounded_inverse_distance with influence_budget 8, max_influences_after_prune 8, unweighted_vertices 0 and worst_weight_sum_error 0.0
(build/3d/best_a14/rig/v21/SKIN_BARE_V21C.json).
coord_fit_worst_residual_blender_units 9.94e-07, coord_map_is_scaled_signed_permutation true,
and the round-trip export_verify.worst_bone_error_cm is 0.000186 across 88 bones (same file).
build/3d/best_a14/rig/bl_pose_mesh_to_rig.py replaced a distance-based carrierwith a discrete harmonic field on the mesh's own edge graph, because the measured leak of the
distance solve was a thigh moving 20.22 cm and a garment moving 19.69 cm when only arm bones were
posed (routeA/REGION_TRAVEL_CARRIER_v1.json, quoted in that script's header).
max_bone_influences 8 (build/3d/best_a14/records/ENGINE_IMPORT_PASS.json).
named so as to invite being quoted as the character's height
(GAME:QA/bench/char_0001_a14_v2_scale_witnesses.json).
Everything above is real engineering. None of it is a *bar*. This document goes and finds the bars.
---
Every source below was read for this document. Grouping is by what it is good for, not by prestige.
Popović, Olga Sorkine. ACM Transactions on Graphics (SIGGRAPH) 2011.
Project page: https://igl.ethz.ch/projects/bbw/ ·
Paper PDF: https://igl.ethz.ch/projects/bbw/bounded-biharmonic-weights-siggraph-2011-jacobson-et-al.pdf ·
ACM: https://dl.acm.org/doi/10.1145/2010324.1964973
Proceedings of the 12th ACM SIGGRAPH/Eurographics Symposium on Computer Animation (SCA), 2013.
https://dl.acm.org/doi/10.1145/2485895.2485919 ·
https://www.semanticscholar.org/paper/Geodesic-voxel-binding-for-production-character-Dionne-Lasa/7067af25003d7f787cfc1cc400dd242d4f18d210
Jared Monsen, David Hill. SIGGRAPH Asia 2023 Technical Communications.
Project page: https://www.dgp.toronto.edu/~rinat/projects/RobustSkinWeightsTransfer/index.html ·
Preprint PDF: https://www.dgp.toronto.edu/~rinat/projects/RobustSkinWeightsTransfer/preprint.pdf ·
ACM: https://dl.acm.org/doi/10.1145/3610543.3626180 ·
Reference implementation (Godot port): https://github.com/V-Sekai/godot-robust-skin-weights-transfer
Jovan Popović. ACM SIGGRAPH 2007.
https://dl.acm.org/doi/10.1145/1276377.1276467 ·
PDF mirror: https://www.cs.toronto.edu/~jacobson/seminar/baran-and-popovic-2007.pdf
Hans Rijpkema, Cyrus A. Wilson (Rhythm & Hues Studios). DigiPro / Digital Production Symposium 2014.
https://dl.acm.org/doi/10.1145/2633374.2633376 ·
https://history.siggraph.org/learning/delta-mush-smoothing-deformations-while-preserving-detail-by-mancewicz-derksen-and-wilson/
methods), Alec Jacobson (automatic methods), J.P. Lewis (example-based), Zhigang Deng
(decomposition). Course notes and slides: https://skinning.org/
Cache, mobile caps) —
https://dev.epicgames.com/documentation/unreal-engine/skeletal-mesh-rendering-paths-in-unreal-engine
https://dev.epicgames.com/documentation/en-us/unreal-engine/fbx-import-options-reference-in-unreal-engine
https://dev.epicgames.com/documentation/en-us/unreal-engine/fbx-skeletal-mesh-pipeline-in-unreal-engine
https://dev.epicgames.com/documentation/unreal-engine/skeletal-mesh-lods-in-unreal-engine
https://dev.epicgames.com/documentation/en-us/unreal-engine/skeletal-mesh-asset-details
https://dev.epicgames.com/documentation/en-us/unreal-engine/skeletal-mesh-sockets-in-unreal-engine
https://dev.epicgames.com/documentation/en-us/unreal-engine/skin-weight-profiles-in-unreal-engine
creation, parenting, renaming, orientation and mirroring, and per-vertex attribute maps. Requires
the Skeletal Mesh Editing Tools plugin) —
https://dev.epicgames.com/documentation/en-us/unreal-engine/skeleton-editing-in-unreal-engine
https://dev.epicgames.com/documentation/unreal-engine/ik-rig-animation-retargeting-in-unreal-engine
https://dev.epicgames.com/documentation/unreal-engine/retargeting-bipeds-with-ik-rig-in-unreal-engine
https://dev.epicgames.com/documentation/unreal-engine/using-python-to-create-and-edit-ik-retargeter-assets-in-unreal-engine
https://docs.unrealengine.com/5.2/en-US/pose-driver-in-unreal-engine/ ·
Epic's Pose Driver Connect / PoseWrangler announcement:
https://www.unrealengine.com/en-US/blog/create-more-realistic-animation-in-less-time-with-pose-driver-connect
https://dev.epicgames.com/documentation/unreal-engine/ml-deformer-framework-in-unreal-engine ·
Deformer Graph —
https://dev.epicgames.com/documentation/en-us/unreal-engine/deformer-graph-in-unreal-engine
UEditorValidatorBase, IsDataValid, EditorValidatorSubsystem, the CI commandlet) —
https://dev.epicgames.com/documentation/unreal-engine/data-validation-in-unreal-engine
mobile bone cap, Nanite incompatibility) —
https://dev.epicgames.com/documentation/metahuman/requirements-and-configuration-settings-for-metahumans-in-unreal-engine
Maintain Max Influences, dropoff, falloff defaults) —
https://help.autodesk.com/cloudhelp/2022/ENU/Maya-CharacterAnimation/files/GUID-CF2C698A-44BB-4CA0-BCB9-DB36500DA812.htm
https://help.autodesk.com/cloudhelp/2019/ENU/Maya-CharacterAnimation/files/GUID-5EFDB81B-E332-4D6C-B1BB-0B989AD2F2C7.htm
https://help.autodesk.com/view/MAYAUL/2025/ENU/?guid=GUID-99189E9D-237F-471E-A02C-BE6593B4828B
FbxSystemUnit class reference — the constructor's scale factor is "the equivalent number of centimeters in the new system unit" and GetScaleFactor() "scales system unit
values to centimeters". Note for the reader: ConvertScene() is documented on this page only as
"Converts a scene from its system units to this system unit" — the page says nothing about which
parts of the scene it touches. https://help.autodesk.com/cloudhelp/2016/ENU/FBX-Developer-Help/cpp_ref/class_fbx_system_unit.html
JavaScript shell that rendered empty for the §6 citation audit, so no claim in this document is
quoted from it.
https://help.autodesk.com/view/FBX/2020/ENU/?guid=FBX_Developer_Help_nodes_and_scene_graph_fbx_scenes_scene_axis_and_unit_conversion_html
armature options, Add Leaf Bones) —
https://docs.blender.org/manual/en/2.81/addons/import_export/io_scene_fbx.html
the canonical write-up of the Blender↔FBX armature scale mismatch —
https://projects.blender.org/blender/blender-addons/issues/47043
working character validator: an enumerated set of individually-named mesh, skeleton and skinning
checks — https://zewt.github.io/zMayaTools/tool-character-validation.html
ruleset of a commercial rig-ingest service (hierarchy grouping, ASCII-only names, unique deforming
joint names, all GEO must be skinned) —
https://help.wonderdynamics.com/character-validation-messages/maya-specific-messages/character-rig-validation/
SK_, SKEL_, PHYS_; "all meshes should be scaled correctly") — https://github.com/Allar/ue5-style-guide
the Abdrashitov et al. method —
https://mitsuaki0321.github.io/maya-fake-tools/en/rig/robust_weight_transfer.html
TransferSkinWeights Dataflow node reference (UE 5.8) —https://dev.epicgames.com/documentation/unreal-engine/node-reference/Dataflow/TransferSkinWeights
named validator rules (an Omni:Geometry group and a Usd:Performance group, including
ColocatedVerticesChecker and DuplicateFaceChecker) running on the Scene Optimizer operations
framework; useful as a shape, not as our tool —
https://docs.omniverse.nvidia.com/extensions/latest/ext_scene-optimizer/performance-validators.html
Production track; Tim Borrelli (5th Cell Media), Ben Cloward (BioWare), Seth Gibson (343
Industries). A Character-TD panel on production rigging methods; cited from its session listing,
not watched — https://gdcvault.com/play/1012716/Technical-Art-Techniques-Character-Rigging
and Adam G. Sidwell. The linked record is the John Wiley & Sons edition, 2011, 395 pp,
ISBN 978-1-118-05876-3 (the work first appeared from Sybex in 2008). A book-length treatment of
deformation setup and rig-pipeline construction; cited as existing and on-topic, and no claim in
this document is sourced to its contents.
https://books.google.com/books/about/Body_Language.html?id=x3cioI3jMNcC
Apply Scalings / Add Leaf Bones / Apply Transform triad —
https://sarahhyperdense.substack.com/p/blender-to-ue5-the-complete-export
https://unrealcommunity.wiki/blender-fbx-pipeline-qw16qyxh
is done in layers rather than on one flat map —
https://rigmarolestudio.com/ngskintools-skinning-tips/
---
Rules are numbered R1…R35, continuous and without gaps, so later passes and the audit can cite
them. Each names the source it comes from and the file in our tree it lands on.
R1 — A weight field must travel along the surface, never through space. This is the single most
load-bearing finding in the skinning literature and we arrived at it independently. Maya's default
production binder is Geodesic Voxel precisely because it computes weights from *geodesic distance
inside the volume* rather than Euclidean proximity, which is what lets it survive non-manifold,
non-watertight, self-intersecting and multi-component meshes (Dionne & de Lasa, SCA 2013; Autodesk
Geodesic Voxel binding manual). Bounded Biharmonic Weights reaches the same place from the other
direction: minimising the Laplacian energy under bound constraints yields influences that are
"shape-aware and localized … even for objects with complex and concave boundaries" (Jacobson et al.,
SIGGRAPH 2011). EVIDENCE, and independently reproduced by us: our own measurement of the
distance-based carrier's leak — a thigh dragged 20.22 cm and a garment dragged 19.69 cm by an
arms-only pose — is the identical failure the literature names, and our replacement (a discrete
harmonic field solved on the mesh's edge graph) is the identical fix.
*Lands on:* build/3d/best_a14/rig/bl_pose_mesh_to_rig.py::harmonic, and the leg chain that
ROUTE_A_RESIDUALS.md OPEN-1 says still needs it.
R2 — Our carrier field has a published parent; name it, and inherit its two missing constraints.
The harmonic-field-with-hard-seeds construction in bl_pose_mesh_to_rig.py is the inpainting stage
of Abdrashitov et al. 2023 and a first-order cousin of BBW. Two constraints the published methods
carry that a bare neighbour-average does not:
We currently clip to [0,1] and then divide by the row sum (W[k] = W[k] / np.maximum(tot, 1e-12)).
That is a valid projection, but it means the *smoothness* claim is about the pre-normalised field,
not the shipped weights.
argument is that unconstrained biharmonic weights go non-local and negative, and the bound
constraints are what stop it.
*Lands on:* bl_pose_mesh_to_rig.py §5, and any future leg-chain field.
**R3 — Confidence-gated transfer, then inpaint: the published two-stage shape for garment and
follower binds.** Abdrashitov et al. copy weights only where a closest-point match passes *both* a
distance and a normal-angle threshold, then solve the remainder as a Laplacian interpolation.
Published defaults from the Maya FakeTools implementation: **distance ratio 0.05 of the bounding-box
diagonal, normal angle 30°, post-smoothing 10 iterations at alpha 0.2, position tolerance 0.0001**,
with optional seam averaging. EVIDENCE (the paper measures against Maya's own transfer).
*Lands on:* the owed follower/garment bind. Today bl_pose_mesh_to_rig.py::bind_rigid gives the
trousers and every head follower a rigid weight 1.0 to a static bone — correct for a carrier that
only poses arms, explicitly *not* correct for a shipped garment.
R4 — Geodesic voxel binding has two hard preconditions; check them or the bind is undefined.
Autodesk states them plainly: the joints must be enclosed inside the mesh volume, and the mesh
normals must point outwards. CRAFT CONSENSUS + manual. Our lane already measures the first
one — bl_pose_mesh_to_rig.py reports arm_joints_vs_silhouette_AFTER_down_pose and
bl_check_containment.py exists for exactly this — but nothing checks normal orientation.
*Lands on:* build/3d/best_a14/rig/bl_check_containment.py, plus a new outward-normal assertion.
R5 — Bone heat is the 2007 ancestor and it is known to accept-and-be-wrong. Baran & Popović's
Pinocchio heat-diffusion solve is the direct ancestor of Blender's bone heat and Maya's Heat Map.
Our own run is a textbook illustration: bone heat accepted 1.0000 of vertices in the matched pose
and still produced a wrong result, because acceptance is a solvability statement, not a quality one
(bl_pose_mesh_to_rig.py header). EVIDENCE, ours. Treat "the binder accepted the mesh" as a
precondition, never as a pass.
R6 — Skin in layers, not on one flat map. Practitioner consensus around ngSkinTools: hold each
influence's contribution as a separate editable layer so a shoulder fix cannot silently unpick an
elbow fix, and so a re-solve can be re-applied under hand corrections rather than over them.
CRAFT CONSENSUS. Our carrier is already layered in spirit — field A (arm swing) times field B
(elbow split) — but the layers are discarded at bake.
*Lands on:* bl_pose_mesh_to_rig.py §5; persist FIELD[a] alongside the FBX so a repair can be
authored against the field rather than against the final weights.
R7 — Choose the skinning method deliberately, per region. Maya exposes Classic Linear, Dual
Quaternion, and Weight Blended (a per-vertex blend map between the two). Dual quaternion
preserves volume around twisting joints; linear does not, which is the candy-wrapper failure.
Manual + craft consensus. We ship linear blend skinning by default and have never declared it.
*Lands on:* a declared field in build/3d/characters/emit_a14_v21_manifest.py.
R8 — UE's influence ladder is 4 → 8 → 12, and 12 is a hard ceiling. From the Skeletal Mesh
Rendering Paths manual: the default vertex factory skins each vertex with 4 or 8 influences
depending on platform; Unlimited Bone Influences mode is theoretically unbounded but *"in practice
the maximum number of influences is capped to 12 because of the way Skeletal Mesh source data is
stored."* EVIDENCE (engine manual).
R9 — Unlimited Bone Influences is a project setting with a documented recommended threshold.
*Project Settings → Engine → Rendering → Skinning*: Use Unlimited Bone Influences (requires an
editor restart) and Unlimited Bone Influences Threshold, where Epic's recommendation is 8 —
so meshes at 9–12 influences take the unlimited path and 0–8 take the fixed path.
*Lands on:* a declared row in the import manifest chain; today
build/3d/characters/CHAR_0001_A14_V21_IMPORT_MANIFEST.json never names the project's setting.
R10 — The influence limit is also a per-LOD build setting. *LOD Build Settings → Bone Influence
Limit*; 0 means "use the project default." Epic's stated purpose is to let a mesh carry high
influences at LOD0 and shed them down the chain for performance and memory.
*Lands on:* build/3d/characters/bl_lod_tooth.py (present, and never run on this asset).
R11 — Game practice caps at 4 far more often than the engine requires. The published zMayaTools
character validator ships a skinning check reading *"Vertices aren't weighted to more than 4
vertices"* — the wording is the source's, the meaning is influences, and the threshold is adjustable,
so read 4 as that tool's shipped default rather than as a fixed industry constant.
CRAFT CONSENSUS. Maya's own bind default is Max Influences 5 ("Default is 5, which produces
good smooth skinning results for most characters") with Maintain Max Influences
available to enforce it continuously. Our own default agrees: both
bl_skin_to_mannequin_BOUNDED.py and bl_skin_to_mannequin_ADAPTED.py default --max-influences 4.
The *shipped* run did not: SKIN_BARE_V21C.json records influence_budget 8 and
max_influences_after_prune 8.
R12 — Normalisation is a mode, not an afterthought, and "post" is what an engine consumes. Maya
offers Interactive / Post / None; Post computes normalised values as the mesh deforms. What ships to
an engine must sum to 1.0 per vertex, full stop. Manual. We already hold this to the floor —
worst_weight_sum_error 0.0 in SKIN_BARE_V21C.json and a live check in
build/3d/best_a14/rig/bl_verify_bind.py line 64.
R13 — Prune to the budget before export, and record what the prune cost. The budget is enforced
at bind time in the DCC, not discovered at export: Maya's *Maintain Max Influences* means the
geometry "cannot have, at any time, a number of influences greater than that specified by Max
Influences" (Bind Skin Options manual). Manual, for the enforcement half. That a prune should
also be *measured* is CRAFT CONSENSUS and, here, a house rule: ours does prune to budget
(ADAPTED.py §"influence budget") and reports max_influences_before_prune /
_after_prune — but reports no *displacement* caused by the prune, which is the number that says
whether the prune was free.
*Audit note:* an earlier revision attributed a 1e-9 zero-threshold and a *Remove Unused Influences*
behaviour to a Maya skinCluster node reference. Neither claim was present at the cited URL, and
that citation has been removed from §1.3. Nothing in §3 rested on it.
**R14 — The FBX unit scale factor is expressed relative to centimetres, and it is metadata, not
geometry.** FbxSystemUnit's scale factor scales system units *to centimetres*. **EVIDENCE (SDK
reference).** This is the root of the whole trap class: a file can *declare* one unit and *contain*
another.
R15 — A scale check that reads a transform is not a scale check. The rule this document
actually needs is the consequence, and the consequence stands on our own measurement, so it is
stated first and sourced honestly second: *only a measurement of the resulting geometry is a
scale check.* EVIDENCE, ours — G11 below is a live instance in a second lane, where a field
derived from component Bounds tracked mesh scale to four decimals in both arms of a control and was
structurally blind to the geometry-level change it was named for.
The *mechanism* usually given for this in FBX practice — that unit and axis conversion act on node
transforms and animation while mesh control-point values are left alone — could not be confirmed
at either source this document originally cited: the FbxSystemUnit class reference documents
ConvertScene() only as "Converts a scene from its system units to this system unit" and says
nothing about what it touches, and the Scene Axis and Unit Conversion page did not render. Treat the
mechanism as CRAFT CONSENSUS, unverified at source and do not quote it as SDK-documented. Nothing
downstream depends on it: R14's centimetre-relative scale factor is verified, and the rule above is
ours.
*This is exactly why* GAME:QA/bench/char_0001_a14_v2_scale_witnesses.json WITNESS_1_IMPORT_BOUNDS
is the right instrument and WITNESS_3_COMPONENT_BOUNDS is not.
R16 — The exporter's scaling mode decides where the ×100 lives. Blender's FBX exporter offers
All Local (units baked into each object transform, FBX scale stays 1.0), FBX Units Scale
(custom scaling into transforms, unit scaling into the FBX scale factor), FBX Custom Scale, and
FBX All; Apply Unit controls whether the unit scale factor is written at all.
CRAFT CONSENSUS — the Blender manual URL would not render for the §6 audit (see §5); "FBX Units
Scale" as an Apply Scalings option is corroborated by the Hyperdense write-up, and the full
four-option list is unverified at source. Our own flag values below are read off our scripts.
Our chain uses apply_scale_options="FBX_SCALE_NONE" with apply_unit_scale=True and
global_scale=1.0 (bl_skin_to_mannequin_BOUNDED.py L1267, ADAPTED.py L822,
bl_skin_rebuilt_to_shipped.py L493, prep_assembly.py L163) — i.e. All Local, everything baked
into transforms, FBX declaring centimetres. That is internally consistent and it is *why* the landed
asset measures 151.1438 cm to four decimals.
R17 — UE's import-side controls are named, and silence about them is a defect. *Convert Scene*
(FBX coordinate system → UE's), *Convert Scene Unit* (FBX units → UE centimetres), *Force Front
XAxis*, and *Import Uniform Scale*. Manual. A manifest that does not declare these has not
declared the import.
R18 — Never let an FBX write the shared skeleton's reference pose by accident. *Update Skeleton
Reference Pose* replaces the Skeleton asset's ref pose with the incoming FBX's, and *Use T0 As Ref
Pose* replaces the mesh's ref pose with animation frame 0. Manual. Both are project-wide blast
radii on a shared skeleton. Our chain already holds this correctly and says so:
update_skeleton_reference_pose stays FALSE throughout (ENGINE_IMPORT_PASS.json → REFUSED).
R19 — Pin the FBX version. Epic states the UE FBX pipeline uses FBX 2020.2 and that a
different export version may produce incompatibilities. Manual. Also from the same page: meshes
must be triangulated, one animation per skeletal-mesh file, one vertex-colour set.
R20 — Publish more than one height witness, and say what each one measures. This is not in any
manual — it is *our* rule, and the industry's absence of it is itself the finding. Four engine-side
numbers for one pawn (151.1438 / 166.720016 / 145.098038 / 143.838257) differ by 21.6 cm, and two
carry names that invite misquotation. EVIDENCE, ours. The two-arm control that resolved it
(staged vs unstaged, changing nothing else) is a method worth generalising to every derived figure.
*Lands on:* GAME:Tools/char/emit_a14_scale_witnesses.py.
R21 — The bind pose is a checkable invariant, and studios check it. zMayaTools validates that
*"the current pose of the skeleton matches the pose the skeleton was in at bind time"* and that
*"the geometry transform matches what it was at bind time."* **CRAFT CONSENSUS (published
validator).** Ours checks the neighbouring property — that the inverse of the authored down-pose
returns the rig to the child ref pose within INV_BAR_CM 0.05
(bl_pose_mesh_to_rig.py §6) — but never asserts bind-pose identity on the *delivered* FBX.
R22 — Joint hygiene is validated, not assumed. From the same published list: stub (non-bound
leaf) joints carry zero joint orient; all joint rotations are zero; every joint carries a label;
labels are unique except for symmetric left/right pairs; left/right labelled joints have a
matching partner; center joints sit at X = 0; joints that are neither matched nor centred have
side None; symmetric joints have symmetric positions, rotations and the same rotate order. From
the Flow Studio ruleset: deforming joints must have unique names and stick to ASCII.
CRAFT CONSENSUS.
R23 — Mesh hygiene is validated too, and the checks are specific. Also from zMayaTools:
non-manifold vertices/edges and lamina edges; exactly one history mesh; no vertex tweaks on the
output mesh or on a tweak node; the output mesh is identical to the base mesh; topological symmetry
across YZ; world-space vertex symmetry across YZ; no overlapping vertices ("usually
unintentional, and can cause bad deformations"). CRAFT CONSENSUS. That last one is our OPEN-3
weld defect, named as a standard check by a published validator years before we hit it.
R24 — Do not export leaf bones into UE. Blender's exporter adds terminal leaf bones by default;
they arrive as phantom *_end bones that clutter the skeleton and interfere with retargeting.
**CRAFT CONSENSUS (widely reproduced; see the Hyperdense pipeline write-up and the UE community
wiki). We already hold this: add_leaf_bones=False on every export in build/3d/ (nine call
sites, verified).
R25 — Apply Transform on an armature export is a trap. It bakes coordinate-system conversion
into vertex data and breaks armatures, skinning and animation. CRAFT CONSENSUS, corroborated by
Blender's own tracker (#47043) documenting armature scale arriving wrong in UE. We do not use it.
R26 — Retargeting has one hard precondition: matching reference poses. Epic's biped retarget
guide states it without an exception clause — if the source is T-posed and the target A-posed, one
retarget pose must be edited so they match. The rest of the recipe: set a retarget root
(typically pelvis/hip) on both IK Rigs; build seven chains for a biped (spine, left arm, right
arm, neck, head, left leg, right leg — a single-bone chain is valid); add IK goals on the feet with
a Limb IK solver whose root bone is set to the thigh; tune the retarget root's motion with the
Scale Horizontal and Translation Offset Z settings. Manual. IK Retargeter assets can be
created and edited from Python,
which is how this becomes a pipeline step rather than a click-path.
R27 — Sockets live on the Skeleton by default and are therefore shared. A socket added to the
Skeleton asset applies to every skeletal mesh using it; a Mesh Socket is the per-mesh escape
hatch. Manual. Consequence for us: retuning the follow camera's socket offsets for a 166.72 cm
figure (ROUTE_A_RESIDUALS.md OPEN-5) must be a *mesh* socket or a component offset, or it moves the
shipped child too.
Assembled from the UE Skeletal Mesh Asset Details reference, the Skeletal Mesh LODs page, Allar's
style guide, the zMayaTools list and the Flow Studio ruleset. CRAFT CONSENSUS. This is the list
that answers the brief's "what studios run before an asset ships."
R28 — The checklist.
tolerance. Allar's guide states the intent plainly: all meshes should be scaled correctly, and
in-engine scale overrides should be rare rather than routine.
transform read. Convert Scene / Force Front XAxis declared.
false; bone count and deform-bone count recorded.
declared budget; no influence crossing the midline on a limb bone; boundary loops (eye apertures,
cut seams) weighted to a single dominant bone.
declared per level; *Bones to Prioritize* set for silhouette-critical joints.
mesh), and its transform is recorded.
material carries the SkeletalMesh usage flag (a material without it is silently swapped for the
engine default at draw time, which renders the character grey while every editor-side check reads
green — our own measured failure, ENGINE_IMPORT_PASS.json → THE_TEXTURE_DEFECT_THAT_TOOK_TWO_TRIES).
is set if capsule shadows are used (spheres and sphyls only).
SK_ / SKEL_ / PHYS_ prefixes; ASCII only; unique deforming joint names.history, triangulated on export.
consensus is stronger than that: the best stress test is real motion-capture data, because it
pushes joints into combinations hand-authored poses never reach.
R29 — Look at it. The numeric battery cannot see a shape failure. This is craft consensus and it
is also written into our own tooling in as many words: bl_rom_render.py's header states that every
numeric check in the lane can pass on a bind that is visibly broken. Our OPEN-0 is that principle
arriving one level higher — the *sighted* ROM read passed too, because it was reading deformation
rather than anatomy.
R30 — UE ships the validation framework; use it rather than only bespoke scripts. From the Data
Validation manual: derive from UEditorValidatorBase and implement CanValidateAsset plus
ValidateLoadedAsset (which must call AssetPasses or AssetFails); or override IsDataValid on a
UObject. C++ and Blueprint validators are discovered automatically at editor startup; **Python
validators must register themselves via UEditorValidatorSubsystem.AddValidator**. Validation runs
on asset save by default, and for CI the commandlet is
UnrealEditor-Cmd.exe <Project>.uproject -run=DataValidation. EVIDENCE (engine manual).
**R31 — The validator's rules should be *data*, not code.** Both published validators we read
(zMayaTools, Flow Studio) expose their checks as an enumerated, individually-reportable list, and the
Omniverse Scene Optimizer models validation as a composable graph. The value is that a failing check
names itself. CRAFT CONSENSUS. Our import driver already does this in spirit: the material
substitution scan in GAME:Tools/char/capture_char_0001_a14.py::scan_material_substitution goes red
and *carries the engine's own reason line*, which is why a grey character can no longer be reported
green.
R32 — Delta Mush is the standard answer to "the bind is coarse and the crease tears." Rhythm &
Hues' Delta Mush smooths arbitrary deformation while preserving the model's original detail; it has
been on *every* character rig at that studio since 2010 and is now in Maya. Its published thesis is
directly ours: it lets riggers use simpler binds and coarser deformers without the artifacts,
and it is light enough to run on crowds. EVIDENCE (paper) + craft consensus (ubiquity). This is
the cheapest available answer to ROUTE_A_RESIDUALS.md OPEN-2 (armpit crease, torso volume loss).
R33 — Corrective shapes are driven by RBF from joint orientation, not hand-keyed. UE's **Pose
Driver node builds a pose-space deformer: a Source Bone read for its orientation, a Drive
Source selecting whether rotation or translation is read, Pose Targets drawn from a Pose
Asset** or from animation curves, and an interpolation configured by a distance method (Euclidean,
Quaternion, Swing Angle, Twist Angle) and a blend function (Gaussian, Exponential, Linear, Cubic,
Quintic) — radial-basis machinery, described by those parameter names rather than by the acronym.
Manual. Epic also ships Pose Driver Connect with a Maya-side PoseWrangler authoring
companion; the announcement page did not render for the §6 citation audit, so treat the specifics of
its export format as unverified and do not plan against them. This is the second answer to OPEN-2
and the only one that fixes shape rather than smoothing it — and the UE-side half, which is the half
we would use, is the verified half.
R34 — The ML Deformer is the AAA ceiling, and its training data is a ROM battery. UE's ML
Deformer approximates high-fidelity deformation at runtime from three inputs: the Skeletal Mesh, an
Animation Sequence covering a wide range of motion, and a Geometry Cache (Alembic) of the
desired deformation in those poses. The trained model's deltas are applied through the Deformer
Graph — the Neural Morph model outputs via the graph's Morph Target node, and the Deformer Graph
asset must be set on the skeletal mesh component to take effect at runtime; it is not automatic.
Manual. Note the
shape of the dependency: the training set *is* a ROM battery with a high-quality target. We already
generate the pose half (bl_rom_render.py); we have no high-quality target half.
R35 — Know the platform ceilings before designing the skeleton. "Mobile platforms have a capped
maximum of 75 bones per Section", which MetaHuman's own requirements restate as
Compat.MAX_GPUSKIN_BONES=75. MetaHumans additionally require r.GPUSkin.Support16BitBoneIndex
("enables support of greater than 256 bone indices for rendering on individual sections") and
r.GPUSkin.UnlimitedBoneInfluences. The MetaHuman requirements page states that **"Nanite
Virtualized Geometry does not support skeletal meshes"** — a version-dated statement on a
fast-moving feature, so re-read that page before relying on it rather than treating it as permanent.
GPU Skin Cache is governed by r.SkinCache.Mode (default 1 = enabled) and
r.SkinCache.RecomputeTangents (default 2 = only on sections that enabled it).
Manual. Our asset is 89 bones — clear of
every ceiling, and worth stating rather than leaving inferred.
---
Ranked by how much of the OPEN board each item closes. Every ADOPT names its landing file.
1. **Bounded support on the leg and torso chains, by the same harmonic-field method already proven on
the arms (R1, R2).** OPEN-1's measured cause is unbounded field support crossing a 2.00 cm gap
between the legs; the arm repair's whole thesis is that an edge-graph field cannot cross a gap
because there is no edge there. The fix is a port, not an invention.
*Lands on:* a leg/torso pass in build/3d/best_a14/rig/bl_pose_mesh_to_rig.py, scored by
bl_weight_census.py against the board's own numbers (calf_l 0.33 on 8,811 far-side verts;
thigh_twist_01_l 0.64 at 17.7 cm past the midline).
2. A declared influence-budget contract, enforced at three places (R8–R11). Pick the number
once, write it into the manifest schema, and gate it at bind, at export and at import. Our own
binder defaults (4) and our shipped run (8) currently disagree with each other and nothing
notices.
*Lands on:* build/3d/characters/emit_a14_v21_manifest.py (a structured
max_influences + influence_budget_declared field, not prose),
build/3d/best_a14/rig/bl_verify_bind.py (assert against the declared budget), and
GAME:Tools/char/import_char_0001_a14_v21.py (fail on mismatch, as it already does for
unweighted_vertices and bind height).
3. **Delta Mush as a smoothing layer, and Pose Driver correctives as the shape fix, for OPEN-2
(R32, R33).** The literature's answer to "coarse bind, torn crease" is not "paint harder." It is
a detail-preserving smooth plus RBF-driven correctives, and Epic ships the second one with a Maya
authoring companion.
*Lands on:* a new deformation stage between rig/ and characters/, plus a PoseAsset +
AnimBP row in the import manifest.
4. **A real skeletal-mesh checklist, executed as a validator rather than remembered (R28, R30,
R31).** We already own most of the checks; what we lack is one enumerated list with a per-check
verdict, and a place it runs that is not "whoever remembers to invoke the script."
*Lands on:* an enumerated SKELETAL_MESH_CHECKLIST in build/3d/characters/, executed
Blender-side by bl_verify_bind.py and engine-side by a
UEditorValidatorBase-derived validator under GAME:Tools/char/ registered via
UEditorValidatorSubsystem.AddValidator, so it also runs on save and under
-run=DataValidation.
5. Declare the whole unit/scale contract in the manifest, not just the measured outcome (R14–R19).
We measure the right thing (imported geometry bounds) and we measure it well. What is missing is
the *declaration*: exporter scaling mode, FBX unit scale factor as written, FBX SDK version, and
the four UE import toggles. A declared contract turns a passing measurement into a reproducible
one.
*Lands on:* build/3d/characters/emit_a14_v21_manifest.py schema char_import_manifest/v2 → v3.
6. Confidence-gated transfer plus inpainting for the followers and the garment (R3). Replace
bind_rigid's blanket weight-1.0 with the published two-stage method at its published defaults
(distance ratio 0.05 of the bbox diagonal, 30° normal angle, 10 smoothing iterations at alpha 0.2).
7. An outward-normal assertion and a bind-pose identity assertion on the delivered FBX (R4, R21).
Two checks, both cheap, both standard, both currently absent.
8. Persist the carrier fields beside the FBX (R6). A repair authored against the field is
reviewable; a repair authored against baked weights is not.
9. Declare the skinning method and the platform ceilings (R7, R35). One line each; removes two
whole classes of "we assumed."
10. A retarget-pose declaration and an IK Rig asset built from Python (R26). Our asset is A-posed
and bound to a child-solved ref pose. The moment any retargeted animation touches it, matching
reference poses stops being optional.
cache of the *correct* deformation) that we do not have and cannot fake. Attempting it before
OPEN-0's anatomy bar exists would train a network to reproduce a figure Josh already graded down.
Revisit once a corrected base mesh plus correctives exist.
boundary. Turning on a project-wide rendering mode to buy headroom we are not using is cost with no
return. Declare the setting; do not change it.
lane is Blender + UE Python. Adopt the *methods* (layered skinning, RBF correctives), take the
UE-side implementations (Pose Driver, Skeletal Editor), skip the DCC.
such.** Epic's MetaHuman requirements page states that Nanite Virtualized Geometry does not
support skeletal meshes. That answers the "why is the character not Nanite" question for now; it
is a statement about a version, not a law, so re-check the page before quoting it forward.
---
For the audit phase. Each gap names the rule it fails, the file it lives in, and the evidence.
Ordered by consequence, not by file.
build/3d/best_a14/rig/bl_skin_to_mannequin_BOUNDED.py L62 and
bl_skin_to_mannequin_ADAPTED.py L61 both default --max-influences 4.
build/3d/best_a14/rig/bl_skin_rebuilt_to_shipped.py L61 defaults 8. The run that actually
shipped recorded influence_budget 8 and max_influences_after_prune 8
(build/3d/best_a14/rig/v21/SKIN_BARE_V21C.json), and the engine read the same
(max_bone_influences: 8, build/3d/best_a14/records/ENGINE_IMPORT_PASS.json). So three files carry
two different defaults, the shipped number is neither script's stated default nor the published game
norm (≤4, zMayaTools), and it sits exactly on UE's fixed-path 8 boundary. Nothing anywhere asserts a
budget. Deviation: no declared contract, and a silent disagreement between our own tools.
build/3d/characters/CHAR_0001_A14_V2_IMPORT_MANIFEST.json carried a structured
"max_influences": 8 inside skinned_lods[0]. Its successor
CHAR_0001_A14_V21_IMPORT_MANIFEST.json carries the same fact only inside a prose sentence
("skin": "... max 8 influences."). A gate can read the first; no gate can read the second.
**Deviation: a machine-checkable field became unparseable across a schema revision that declared
itself the same version (char_import_manifest/v2).**
The exporters are consistent and correct — apply_scale_options="FBX_SCALE_NONE",
apply_unit_scale=True, global_scale=1.0 at bl_skin_to_mannequin_BOUNDED.py L1267,
ADAPTED.py L822, bl_skin_rebuilt_to_shipped.py L493, prep_assembly.py L163,
prep_for_house_solve.py L97 — but no record states what unit scale factor the FBX carries, and
no record states the UE-side *Convert Scene* / *Convert Scene Unit* / *Force Front XAxis* /
*Import Uniform Scale* values used. The proof that scale is right is entirely the measured import
bounds (151.1438 vs 151.1438). That is a good instrument and it is exactly the right kind, per R15 —
but it is a *witness*, not a *contract*, and a witness cannot tell you which of the two sides moved
when it eventually disagrees. The trap is live in the same lane: the roundtrip OBJ carries
figure_height_units 16680.56 — the modelled 166.72 cm at ×100 — and OBJ carries no unit
metadata at all. Deviation: the declaration half of R14–R17 is absent everywhere.
build/3d/best_a14/rig/bl_pose_mesh_to_rig.py::bind_rigid gives each follower and the trousers a
single 1.0 weight on head or on the static bone. Inside the carrier that is *correct and measured*
— the script proves it with a clearance check and a field-reach probe, and refuses to assume it. But
the V2.1 groomed asset (SK_CHAR_0001_A14_V21_GROOMED, 144,662 verts, 22 slots) ships that same
rigid follower bind into the engine, and GAME:Tools/char/import_char_0001_a14_v21.py L363 asserts
it as a *requirement*: it fails if follower vertices are not a single 1.0 weight on head. A
head-rigid groom is defensible; a rigidly-bound garment is not — the published method for exactly
this case (garment weight transfer from a body) is R3, and its stated motivation is that closest-point
copies fail on non-skin-tight garments. **Deviation: no transferred/inpainted solve exists anywhere
in the tree; the rigid bind is enforced as canon by the importer.**
Both manifests declare LOD0-only and say why honestly (LOD_CHAIN_DECLARED_ABSENT). The tool exists
— build/3d/characters/bl_lod_tooth.py — and has not been run on this asset. Meanwhile the shipped
SK_CHAR_0001_CHILD carries four LODs (21154/11622/6340/3170 tris). Consequently **Bone Influence
Limit, Bones to Remove, Bake Pose and Bones to Prioritize are unset by construction**, and the
character is a 172k-triangle single-LOD skeletal mesh in a game that will field crowds.
Deviation: an entire checklist row is structurally unreachable until the chain is built.
Nothing in build/3d/ or GAME:Tools/char/ enumerates or asserts sockets.
ROUTE_A_RESIDUALS.md OPEN-5 asks for socket offsets to be retuned for a 166.72 cm figure, and the
asset is bound to /Game/Characters/Mannequins/Meshes/SK_Mannequin — the shared skeleton, per
ENGINE_IMPORT_PASS.json. Per R27, a socket edited on the Skeleton asset moves every mesh using it,
including the shipped child. **Deviation: no socket check exists, and the boarded fix is written in a
way that could silently move a shipped asset.**
bl_verify_bind.py checks three genuinely good things — zero-weight vertices, boundary-ring weight
coherence, and lateral bleed — and its header is explicit that these are the things a ROM sheet
cannot see. It does not check: that the delivered skeleton sits in its bind pose; that the geometry
transform matches bind time; that normals point outward; that there are no overlapping vertices.
The last one is our own OPEN-3 (35 shared hand/thigh vertices), which the published zMayaTools list
carries as a standard check. bl_pose_mesh_to_rig.py checks the *adjacent* invariant — the inverse
pose returns within INV_BAR_CM 0.05 — but on the in-memory armature, not on the exported file.
Deviation: four published standard checks absent; one of them is a defect we shipped.
Every tooth in the chain is a bespoke script: bl_verify_bind.py, bl_weight_census.py,
bl_rom_render.py, GAME:Tools/char/import_char_0001_a14_v21.py,
GAME:Tools/char/capture_char_0001_a14.py::scan_material_substitution. None derives from
UEditorValidatorBase; none is registered with UEditorValidatorSubsystem. There is therefore **no
validation on asset save and no -run=DataValidation CI pass**, and harness/run_gates.py contains
no rig, skin, FBX or skeletal check whatsoever (grep: zero hits). A landed asset that later drifts —
someone re-imports at a different scale, someone edits the shared skeleton — is caught by nothing.
Deviation: the engine ships the framework and we do not use it.
bl_pose_mesh_to_rig.py::seam_check enforces that no hard-1 seed vertex shares an edge with a
hard-0 seed vertex, on the argument that such an edge is a tear the field is powerless to soften
because both ends are pinned. The first run scored 137 such edges at the armpit and tore there.
I found no published equivalent in BBW, geodesic voxel binding, or the weight-inpainting paper —
those methods sidestep the problem by construction (they solve over a smooth domain with soft
handles) rather than by checking seeds. This is a genuine house contribution and it should be named
as such rather than buried in a comment. **Deviation is in the other direction: we are ahead here,
and the guard is currently armed only on the arm fields.**
This is the board's own OPEN-0, restated against the literature so the audit can see it is not
peculiar to us. Every published rig-validation list in §1.4 validates preservation and hygiene:
weights sum to one, no unweighted vertices, no non-manifold edges, bind pose intact, joints labelled,
symmetry held. Not one of them validates that the *character is anatomically right*, because in every
studio pipeline that question was answered upstream by a modeller and an art director before the
mesh ever reached a rigger. Our pipeline has no such upstream. The consequence is precisely
OPEN-0: a gaunt, wrong-shouldered mesh passes every check in §2.5 and arrives in-engine wearing
green. Deviation: we inherited a validation philosophy that assumes a human gate we do not have.
The remedy is not more rig checks — R29 says the rig battery cannot see it — it is the ANATOMY BAR
the board already ordered, sitting *before* the rig, and this document explicitly declines to put it
inside the rigging validator where it would be measuring the wrong stage.
MeasureRenderedFigure publishes a blind field under an honest-sounding name. *(R15, R20)*Already boarded as OPEN-7, restated here because R15 explains *why* it is wrong rather than just
*that* it is: UHumanityLocomotionProbeSubsystem::MeasureRenderedFigure derives RenderedHeightCm
from component Bounds, which do not reflect SetRefPoseOverride. Per R15, a measurement taken off a
transform-derived quantity cannot see a geometry-level change — the ref-pose override rescales limbs,
and uniform component bounds are blind to it by construction. The two-arm control proves it: the
field tracked mesh scale to four decimals in both arms (×1.122807 exactly) and equalled
bind_height × mesh_scale in both. The shipped child's feel records carry the same blind field.
**Deviation: a witness named as evidence about a thing it structurally cannot measure — the exact
class R15 warns about, present in a second lane.**
---
its session listing (verified: GDC 2010, Production track, Borrelli / Cloward / Gibson); its
contents are not quoted as evidence anywhere above. A second talk, "Freeform Animation Rigging:
Evolving the Animation Pipeline", was cited in the first revision via a Class Central listing
(.../youtube-freeform-animation-rigging-evolving-the-animation-pipeline-158029); that URL
refused retrieval on every attempt in the §6 audit and the talk's existence could not be
independently confirmed, so the citation was removed. No rule depended on it.
refused retrieval (9.1 MB binary; HTTP 403). The distance ratio 0.05 / angle 30° / 10 iterations /
alpha 0.2 defaults in R3 come from the Maya FakeTools implementation documentation, not from
the paper. Treat them as a working starting point, not as the authors' published values.
and the current-version URL returned HTTP 403 during the §6 audit. The Apply Scalings option names
and the Add Leaf Bones default in R16 and R24 therefore rest on two independent practitioner
sources that *did* render — the Hyperdense export write-up (which names "FBX Units Scale" as an
Apply Scalings option and describes Add Leaf Bones as on by default) and the UE community wiki
(which independently instructs unchecking Add Leaf Bones) — not on the Blender manual itself. The
four-way option list (All Local / FBX Units Scale / FBX Custom Scale / FBX All) is **unverified at
source**; our own exporter flags are read off our scripts and are unaffected.
default plus Maya's default of 5.** It is a weak-to-moderate prior, not a measured bar — weaker
than the first revision implied, since the zMayaTools threshold is user-configurable. If our own
A/B shows 8 influences buying visible quality at the shoulder, the number to change is the
*declaration*, not the practice of declaring.
---
An independent pass re-fetched the sources in §1 and checked that each exists and says what this
document claims. 24 of the ~35 cited sources were sampled, chosen to cover every source that a
rule in §2 quotes or leans on. Method: direct fetch of each URL; for the ACM DOIs (which refuse
automated retrieval) bibliographic data was confirmed against the Crossref API
(https://api.crossref.org/works/<doi>) and, where available, publisher project pages.
Verified exactly as cited — no change needed. All five peer-reviewed papers confirmed by DOI
(BBW 10.1145/2010324.1964973; geodesic voxel binding 10.1145/2485895.2485919; robust skin weights
transfer 10.1145/3610543.3626180; Pinocchio 10.1145/1276377.1276467; Delta Mush 10.1145/2633374.2633376
— all titles, author lists, venues and years match §1.1, including Delta Mush's four-author list).
The SIGGRAPH 2014 skinning course and its four presenters. Maya Bind Skin Options (Max Influences
default 5; Classic Linear / Dual Quaternion / Weight Blended; Interactive / Post / None). Maya
Geodesic Voxel binding, including both preconditions in R4 verbatim. UE Skeletal Mesh Rendering
Paths — the 4-or-8 default, the "capped to 12" quote verbatim, the recommended threshold of 8, the
0-means-project-default behaviour, the 75-bone mobile cap, and both skin-cache CVar defaults. UE FBX
Import Options (all six toggles in R17 and R18). UE FBX Skeletal Mesh Pipeline (FBX 2020.2,
triangulation, one animation per file). UE Retargeting Bipeds (matching reference poses, retarget
root, the seven named chains, Limb IK). UE Skeletal Mesh LODs. UE Skeletal Mesh Sockets (skeleton
vs mesh socket). UE Data Validation (every API name in R30, including the Python AddValidator
requirement and the commandlet). UE Pose Driver. UE ML Deformer. UE Skin Weight Profiles and
Skeleton Editing. MetaHuman requirements (all three CVars and the Nanite statement). zMayaTools
character validation. Wonder Dynamics / Flow Studio rig validation. Maya FakeTools robust weight
transfer — all five R3 defaults matched exactly (0.05, 30°, 10, 0.2, 0.0001). Allar's UE5 style
guide. Blender issue #47043. FbxSystemUnit (the centimetre-relative scale factor of R14). The
V-Sekai reference implementation. The Hyperdense and UE community wiki pipeline write-ups.
GDC Vault 1012716.
Repaired — a claim the cited source does not carry.
ConvertScene() acts on node transforms and animation whileleaving mesh vertex values alone was labelled EVIDENCE (SDK docs + forum note). The
FbxSystemUnit reference documents ConvertScene() in one sentence that says nothing about what
it touches; the Scene Axis and Unit Conversion page is a JS shell that renders empty; the Autodesk
forum thread returns 403. R15 was rewritten to lead with the consequence (which our own G11
evidence carries independently) and to mark the mechanism CRAFT CONSENSUS, unverified at source.
attributed to a Maya skinCluster node reference. That URL does not serve a skinCluster node
reference and carries neither claim. Both specifics were removed, the citation was dropped from
§1.3, and R13 was re-anchored on the verified *Maintain Max Influences* enforcement.
ISBN 978-0-470-17387-9) does not describe the record at the cited Google Books id, which is the
2011 Wiley edition, 395 pp, ISBN 978-1-118-05876-3. Corrected to match the link.
enumerated set of individually named validator rules on the Scene Optimizer operations framework.
Corrected. R31's actual point — that a failing check should name itself — is unaffected and holds.
and its threshold is adjustable; the quote was clipped and the adjustability omitted, which
overstated 4 as a fixed industry constant. Both fixed here and in §5.
motion was attributed to *Scale Horizontal*. Reworded to the verified framing.
manual's actual account (deltas applied via the graph's Morph Target node; the graph asset must be
set on the component). Pose Driver: the node's parameters are verified, but the Pose Driver
Connect announcement page returns 403, so the PoseWrangler JSON-plus-FBX export detail is now
marked unverified.
removed. The Nanite statement is verified on Epic's MetaHuman page and is now attributed to that
page and marked version-dated rather than asserted as permanent.
Maya skinCluster citation (does not carry the claims made of it).
No fabricated source was found. Every source that could be retrieved exists, is correctly
attributed to its authors and venue, and is on the topic claimed. The defects were of a different
class: a real source cited for a claim it does not make, and one book cited at the wrong edition.
The §2 rules survive the audit — R13 and R15 needed their *sourcing* rebuilt, not their *content*
withdrawn, and no item in §3 WHAT WE ADOPT rested on a repaired claim.