Vhi.StandardPose
VHI_godot¶
Vhi¶
StandardPose Class¶
The one place that knows what a standard value means in rig degrees.
Inheritance System.Object → StandardPose
Remarks¶
A standard +1 is the direction the DOF's name denotes, 0 is rest, and
the domain is [-1, 1]. AtPlusOne states, per joint and axis, the
rotation that +1 produces — so a target multiplies, a reader divides, and
neither carries a sign of its own.
Positive X is flexion on this rig. That is not what
MovementPoses appears to say, and the appearance is what this class exists
to end. Those rows were authored in Unity's convention and reached the skeleton through
ApplyMovementPose, which interpolated with a negated sine and so rendered
their opposite: a held Fist put bone 4 at +85°, never the
tabulated -85°. Reading the table alone gave the wrong answer, and everything that
did — both skeletons' gain tables, this class's own sign vector, the contract suite's
direction gate — agreed with each other and disagreed with the hand. The table is now
stated in rig degrees and the animation interpolates plainly, so there is one convention
and it is this one.
Channel 1 is abduction and the fist's thumb is adducted, so a standard fist
is [+1, -1, +1, +1, +1, +1, …] — the thumb comes across the fingers as it curls.
That is a fact about hands, not a quirk of the rig, and it is why the thumb is the digit
that exposes a direction error: it is the only one whose flexion is not symmetric
front-to-back, so a hand bending entirely the wrong way still looks plausible until you
watch the thumb.
Fields¶
StandardPose.AtPlusOne Field¶
Rig degrees produced by standard +1, per joint: (X, Y, Z).
Field Value¶
System.Collections.Generic.Dictionary<System.Int32,System.Single[]>
Remarks¶
Keyed by the joint indices both skeletons use — 0 wrist, 1-3 thumb, 4-6 index, 7-9
middle, 10-12 ring, 13-15 pinky. X is flexion, Z abduction; a zero means the channel
does not move that joint on that axis, which is not the same as it moving by nothing
(see JointsMovableOnAxis). Declared after Wrist because it uses
it — a static initializer runs in declaration order, and the other way round joint 0
silently becomes null and the wrist stops moving.
StandardPose.Wrist Field¶
Joint 0's rotation at standard +1, in degrees: (X, Y, Z).
Field Value¶
Remarks¶
The wrist. Joint 0 is WaveBone_1, the common ancestor of all five digit
chains, so rotating it turns the whole hand — which is what a wrist does.
Every number here is a calibration, not a derivation. An earlier version of this comment derived X from the finger bones — Fist against IndexExtension — and that reasoning was wrong twice over: it read the pose table without the animation's negation, and a bone's local basis is its own. Nothing about the fingers constrains which way joint 0 turns.
X = +30 — WristUpDown gives the magnitude as
±30; the sign says standard +1 flexes, matching the digits.
Z = +20 — WristLeftRight gives ±20 and names
neither side: "left/right" says which axis, not which is abduction.
Y = +179 has no rig-side evidence at all. No movement in the library
touches joint 0's Y, so both magnitude and sign are picked: 179° each way to stay
clear of the ±180° Euler ambiguity, positive so that +1 is pronation.
There is no forearm, so what twists is the hand about its own long axis.
All three want confirming against the hand rather than by reading, and X now has the digits to check against. Flip a sign here and nothing else needs to change.
Methods¶
StandardPose.Clamp(float) Method¶
A standard value clamped to its domain, for storing in a pose vector.
Returns¶
StandardPose.Clamp(List\<float>) Method¶
Clamp a whole pose in place, for as many channels as are present.
StandardPose.Standard(int, int, float) Method¶
Rendered degrees → the standard value that produced them. The inverse of Degrees in range, so a read-back round-trips rather than flipping.