feat(body): pose the arms down, add a front-angle shot

The character now stands with its arms at its sides instead of in a bind A-pose,
and there is a second camera to prove it: the third-person shot only ever showed
the pawn's back, so a front-facing pose defect was invisible in review.

  demo-third-person-front  camera on the road, ~6 m in front, looking back north
                           at the pawn; embedded in Screenshots/README.md as shot 7.

The pose work itself is a chain of measured findings, all recorded in TODO.md:

- clip data is exported relative to the REST pose, so arms-down offsets held only in
  the keys arrived as a ±20 degree swing around an A bind;
- a rest-pose bake alone does not move the mesh: the MPFB mesh has shape keys, the
  armature modifier cannot be applied while they exist, and the vertices stayed in
  the A shape (X span unchanged at 1.051 m). Clearing the shape keys, baking the
  deformation into the vertices and re-binding is what made bind and clips agree.

Not settled, and left as an open item rather than a claim: the base pose uses
inverted signs to compensate for the FBX axis mapping, the upper arms clip into the
torso, and the fingers splay. An aim-based pose module was written and then removed
- applied without the vertex bake it produced arms raised in a V, and a half-working
shared module is worse than none. The proper solve is 0.2.2: apply the standing pose
at character creation, then author clips against that bind.
This commit is contained in:
zwitschi committed 2026-11-09 11:28:29 +01:00
1 parent a1f5989cbb
commit 8993fd83c4
39 files changed
+81 -47

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+19 -5
View File
@@ -106,13 +106,27 @@ Known gaps in this first pass, recorded rather than hidden:
What this shot is evidence for: What this shot is evidence for:
- The pawn carries a visible skeletal body with the warm skin material, and a spring-arm camera with collision testing. The **V** toggle swaps first and third person; the shipped default stays first person and the review passes `-thirdperson`. - The pawn carries a visible skeletal body with the warm skin material, and a spring-arm camera with collision testing. The **V** toggle swaps first and third person; the shipped default stays first person and the review passes `-thirdperson`.
- **The idle clip now drives the body.** The arms hang at the sides rather than standing out in a bind A-pose, which is what the first three captures of this shot showed. - **The idle clip drives the body and the arms hang at the sides.** Earlier captures of this shot showed a bind A-pose.
What is still not right, and is tracked: Still open, tracked in `TODO.md`:
- **The arms hang too far forward and the hands splay outward**, so the pose reads as a person standing awkwardly rather than at rest. The base pose is applied to the rest pose with inverted signs (the FBX axis mapping flips it); the elbow and hand orientation still need work, and that belongs to the `0.2.2` skin/animation tuning pass rather than to this rig. - The arms hang close enough to clip into the torso at the shoulder, and the fingers splay slightly. That is the `0.2.2` pose-and-skin tuning pass, not this rig.
- **The walk clip has no shot of its own.** It imports and its curves carry a ±18° arm swing and a 0.45 rad hip swing, but nothing has captured it in motion; a walking shot needs a camera that follows a moving pawn. - **Camera collision is implemented but unproven:** the spawn has open space behind it, so no shot exercises the arm shortening.
- **Camera collision is implemented but unproven:** the spawn point has open space behind it, so no shot exercises the arm shortening.
---
## 7. Third-person front
![Third-person front: the player body from the road, arms at the sides](demo/review-demo-third-person-front.png)
- **File:** `demo/review-demo-third-person-front.png`
- **View:** from the road, ~6 m in front of the pawn, looking back north. The pawn spawns facing +Y, so this is its front
- **Expected content:** both arms hanging at the sides with the hands by the hips, face and chest visible
- **Verified:** ☑ 2026-11-09 · **Approved:** ☐ pending
**Why the shot exists:** the third-person shot only ever shows the pawn's back, so a pose defect on the front — arms out, hands splayed, a face pointing the wrong way — was invisible in review. This angle is the check for it.
What it shows: the arms hang down with a soft elbow bend and the hands sit at hip height. What it still shows wrong: the upper arms sit close enough to the torso to clip at the shoulder, and the fingers point outward-forward rather than hanging relaxed.
--- ---
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -17,7 +17,8 @@ Actionable task list for this project. This file is the single, central place fo
- [x] Import character into Unreal; validate skeleton, scale, and materials. Done: `/Game/Test/Character` — `SkeletalMesh` (138 bones), `Skeleton`, warm `M_Character_Export` material with baked `T_Character_Diffuse`. - [x] Import character into Unreal; validate skeleton, scale, and materials. Done: `/Game/Test/Character` — `SkeletalMesh` (138 bones), `Skeleton`, warm `M_Character_Export` material with baked `T_Character_Diffuse`.
- [x] Promote the character asset into a reusable NPC prefab (visible body, collision capsule, idle pose) ready for pedestrians (`0.5.0`) once the third-person body lands. Done 2026-11-07: `AGigLineNPCPerson` (see the 0.1.0 Character-development item); `0.5.0` reuses it as the pedestrian base. - [x] Promote the character asset into a reusable NPC prefab (visible body, collision capsule, idle pose) ready for pedestrians (`0.5.0`) once the third-person body lands. Done 2026-11-07: `AGigLineNPCPerson` (see the 0.1.0 Character-development item); `0.5.0` reuses it as the pedestrian base.
- [x] Create basic idle/walk animation set. Done 2026-11-09: `Tools/character_anim_build.py` authors `GigLine_Idle` (60 f) and `GigLine_Walk` (30 f) at 30 fps from parametric cycles, and `Tools/ue_character_anim_import.py` imports them. Both AnimSequences verified in `/Game/Test/Character`: Idle 1.967 s, Walk 0.967 s. Limb axes were **measured** on the rig, not assumed — the probe rotated `upperleg01.L` 0.5 rad per axis and read `foot.L`, which showed X is the fore/aft swing (Y twists, Z abducts). - [x] Create basic idle/walk animation set. Done 2026-11-09: `Tools/character_anim_build.py` authors `GigLine_Idle` (60 f) and `GigLine_Walk` (30 f) at 30 fps from parametric cycles, and `Tools/ue_character_anim_import.py` imports them. Both AnimSequences verified in `/Game/Test/Character`: Idle 1.967 s, Walk 0.967 s. Limb axes were **measured** on the rig, not assumed — the probe rotated `upperleg01.L` 0.5 rad per axis and read `foot.L`, which showed X is the fore/aft swing (Y twists, Z abducts).
- [~] Verify animation plays correctly on the imported rig. **Fixed 2026-11-09**: the clip now drives the body — shot 6 shows the arms hanging at the sides instead of an A-pose. Two causes, both proven by measurement rather than guessed: (1) `PlayAnimation` needs the component in `AnimationSingleNode` with a live single-node instance, and the body is hidden at construction, so the first call could land before the component was ready and never retry; the code now sets the mode, calls `SetAnimation` + `Play`, and re-asserts while the instance is missing. (2) the arms-down offsets were carried only in the clip keys, which the exporter writes relative to the rest pose — so they arrived as a ±20° swing around an A-posed bind; they are now baked into the rest pose before the clips are authored (`apply_base_pose`). **Still open:** the idle pose reads awkwardly (arms hang forward, hands splay) because the base is applied with inverted signs to compensate for the FBX axis flip, and the walk clip has never been captured in motion. Earlier evidence: the pawn's mesh is bound, both clips resolve, and the run logs `GigLine: playing body clip Character_AnimHuman_rig_GigLine_Idle`, but shot 5 still renders the body in bind pose (arms out). So `PlayAnimation` is called and the pose is not applied — next step is to check whether the imported clip carries bone curves at all (the FBX bake may be sampling only keyed bones) or whether the component needs `SetAnimationMode(AnimationSingleNode)` before `SetAnimation`/`Play`. - [~] Verify animation plays correctly on the imported rig. **Playback works since 2026-11-09**: the clip drives the body and the arms hang at the sides (shots 6 and 7). Three defects were found and fixed, each by measuring rather than guessing: (1) `PlayAnimation` on a hidden component never took effect, so the code now sets `AnimationSingleNode`, calls `SetAnimation` + `Play`, and re-asserts while the single-node instance is missing; (2) the arms-down offsets lived only in the clip keys and the exporter writes clip data relative to the rest pose, so they arrived as a ±20° swing around an A-posed bind — they are baked into the rest pose before the clips are authored; (3) a rest-pose bake alone does **not** move the mesh, because the MPFB mesh carries shape keys, the armature modifier cannot be applied while they exist, and the vertices stayed in the A shape (measured: X span unchanged at 1.051 m) — baking the deformation into the vertices, clearing the shape keys and re-binding is what made the bind match the clips. **Still open — the pose is not settled:** the base pose is applied with inverted signs to compensate for the FBX axis mapping, the upper arms clip into the torso, and the fingers splay. An aim-based pose module (`Tools/character_pose.py`) was attempted and removed: applied without the vertex bake it produced arms raised in a V, and a half-working shared module is worse than none. The proper solve belongs to `0.2.2`: build the character with the standing pose applied at creation (the `mpfb_character_export.py --pose idle` path), then author clips against that bind.
- [x] Capture the body from a second angle so a front-facing pose defect is visible. `demo-third-person-front` added to the shot list and to `Screenshots/README.md`; the third-person shot alone only showed the pawn's back.
### Camera and controls ### Camera and controls
+4
View File
@@ -319,6 +319,10 @@ try:
# the visible body and its idle clip are what the shot is for. # the visible body and its idle clip are what the shot is for.
# Demo_PlayerStart is at (-13336, -1150, 600), yaw 90 (facing +Y). # Demo_PlayerStart is at (-13336, -1150, 600), yaw 90 (facing +Y).
("demo-third-person", unreal.Vector(-13336, -1750, 780), unreal.Vector(-13336, -1150, 560), 58.0), ("demo-third-person", unreal.Vector(-13336, -1750, 780), unreal.Vector(-13336, -1150, 560), 58.0),
# Front view of the same pawn: the third-person shot only ever shows its
# back, so a pose defect there is invisible. The pawn spawns facing +Y
# (yaw 90), so the camera stands on the road side and looks back north.
("demo-third-person-front", unreal.Vector(-13336, -520, 700), unreal.Vector(-13336, -1150, 540), 55.0),
] ]
seq = spawn(unreal.GigLineShotActor, unreal.Vector(0, 0, 300), "ShotSequencer") seq = spawn(unreal.GigLineShotActor, unreal.Vector(0, 0, 300), "ShotSequencer")
if seq: if seq:
+12
View File
@@ -72,6 +72,18 @@
"Art/reference/hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg" "Art/reference/hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg"
], ],
"expect": "Third-person view of the player body standing on the north sidewalk, full figure visible from behind, the hero facade across the street, daylight" "expect": "Third-person view of the player body standing on the north sidewalk, full figure visible from behind, the hero facade across the street, daylight"
},
{
"name": "demo-third-person-front",
"shot": "Screenshots/demo/review-demo-third-person-front.png",
"size": [
1920,
1080
],
"references": [
"Art/reference/hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg"
],
"expect": "Front view of the player body from the road: both arms hanging at the sides, hands down by the hips, face and chest visible, hero facade behind the camera"
} }
] ]
} }