fix(vagrant): remove head sprite_rot + invert signed-angle cross-sign

Two fixes from manual interactive verification after iteration-3:

1. Head 90° CCW off → removed sprite_rot=-90 from head bone. The
   v0.3.3 sprite_rot fix was based on misobservation: at that point
   the persistent-state-rate-limit bug was active and head was
   wiggling within ±10° of an arbitrary initial direction, perceived
   as 90° CW off. With v0.3.2+ persistent-state fix and v0.4.0 slerp,
   head rotates correctly when sprite-natural-face is -Y (matching
   body-sprite convention).

2. Legs walked in inverted sector → signed_angle_2d cross-component
   was using Y-up math convention but Sporel screen-coords are Y-down.
   With Y-down, what's CCW in math is CW visually. Flipping the cross
   sign aligns sector selection: body up + player walks right → CW
   visually → walk_right_lower (was wrongly returning walk_left).

Front/back leg-anchor issue (#3 from user report) deferred — likely an
optical-overlap artifact from rotated body sprite + world-frame leg
positions, will reassess after #1+#2 fixes are visually verified.
This commit is contained in:
Axel Meyer
2026-05-18 21:38:43 +02:00
parent e6e4e3805b
commit 3f176f6105
2 changed files with 5 additions and 3 deletions

View File

@@ -40,9 +40,11 @@ local ci_assets_traced = false
local WALK_ANIMS = {"walk_fwd_lower", "walk_back_lower", "walk_left_lower", "walk_right_lower"} local WALK_ANIMS = {"walk_fwd_lower", "walk_back_lower", "walk_left_lower", "walk_right_lower"}
-- Signed angle between two 2D vectors (in degrees, range [-180, 180]). -- Signed angle between two 2D vectors (in degrees, range [-180, 180]).
-- Returns the signed angle from v1 to v2, positive = counter-clockwise (left). -- Sporel uses Y-down screen-coords. Substrate's math assumes Y-up; the cross
-- component is flipped so "positive num = move-direction is CCW from body-fwd
-- in screen-coords" matches substrate's "positive num = walk_left sector".
local function signed_angle_2d(v1x, v1y, v2x, v2y) local function signed_angle_2d(v1x, v1y, v2x, v2y)
local cross = v1x * v2y - v1y * v2x local cross = v1y * v2x - v1x * v2y -- Y-down flip
local dot = v1x * v2x + v1y * v2y local dot = v1x * v2x + v1y * v2y
return math.deg(math.atan(cross, dot)) return math.deg(math.atan(cross, dot))
end end

View File

@@ -5,7 +5,7 @@
{ "id": "root", "parent": null, "rest": {"x": 0, "y": 0, "rot": 0}, "z_order": -1 }, { "id": "root", "parent": null, "rest": {"x": 0, "y": 0, "rot": 0}, "z_order": -1 },
{ "id": "lower_control", "parent": "root", "rest": {"x": 0, "y": 0, "rot": 0}, "virtual": true }, { "id": "lower_control", "parent": "root", "rest": {"x": 0, "y": 0, "rot": 0}, "virtual": true },
{ "id": "body", "parent": "root", "rest": {"x": 0, "y": 0, "rot": 0}, "z_order": 2, "texture": "body_001", "look_at": "soft", "look_at_slerp": 6 }, { "id": "body", "parent": "root", "rest": {"x": 0, "y": 0, "rot": 0}, "z_order": 2, "texture": "body_001", "look_at": "soft", "look_at_slerp": 6 },
{ "id": "head", "parent": "body", "rest": {"x": 0, "y": -3, "rot": 0, "rot_min": -60, "rot_max": 60}, "z_order": 6, "texture": "head_001", "look_at": "aim", "sprite_rot": -90 }, { "id": "head", "parent": "body", "rest": {"x": 0, "y": -3, "rot": 0, "rot_min": -60, "rot_max": 60}, "z_order": 6, "texture": "head_001", "look_at": "aim" },
{ "id": "shoulders", "parent": "body", "rest": {"x": 0, "y": 0, "rot": 0}, "z_order": 5, "texture": "shoulder_001" }, { "id": "shoulders", "parent": "body", "rest": {"x": 0, "y": 0, "rot": 0}, "z_order": 5, "texture": "shoulder_001" },
{ "id": "upper_arm_l", "parent": "shoulders", "rest": {"x": -19, "y": -3, "rot": 0, "scl": [-1, 1]}, "z_order": 3, "texture": "upper_arm_001" }, { "id": "upper_arm_l", "parent": "shoulders", "rest": {"x": -19, "y": -3, "rot": 0, "scl": [-1, 1]}, "z_order": 3, "texture": "upper_arm_001" },
{ "id": "upper_arm_r", "parent": "shoulders", "rest": {"x": 20, "y": -4, "rot": 0}, "z_order": 3, "texture": "upper_arm_001" }, { "id": "upper_arm_r", "parent": "shoulders", "rest": {"x": 20, "y": -4, "rot": 0}, "z_order": 3, "texture": "upper_arm_001" },