From fadaf3b8a31df72fdb991e0b2fb894d986f6a822 Mon Sep 17 00:00:00 2001 From: Axel Meyer Date: Mon, 18 May 2026 21:47:34 +0200 Subject: [PATCH] =?UTF-8?q?fix(puppet):=20v0.4.1=20=E2=80=94=20normalize?= =?UTF-8?q?=20target=5Flocal=20before=20clamp=20(south-flick=20fix)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When body's world.rot crosses ±π (e.g., body facing south), target_local in the look-at-block could momentarily be ≈±2π. Without normalization, the snap-branch wrote that raw value to state.angle, then rot_min/rot_max clamp produced a discontinuous jump (head 'flicked sideways' when body faced south, per manual interactive test). Fix: normalize target_local to (-π, π] BEFORE the snap/slerp/rate-limit branch and BEFORE clamp. Symmetric handling regardless of which smoothing mode the bone uses. --- init.lua | 6 ++++++ manifest.lib | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 0179523..0000c6c 100644 --- a/init.lua +++ b/init.lua @@ -980,6 +980,12 @@ update_bone_recursive = function(p, b, dt) -- atan(dx, -dy): rot=0 when target is straight up, rot=pi/2 when target is to the right. local world_angle = math.atan(dx, -dy) local target_local = world_angle - pa + -- Normalize target_local to (-π, π] so snap/clamp don't see ±2π + -- discontinuities when parent.world.rot crosses ±π (e.g., body + -- facing south wraps parent.world.rot near ±π and target_local + -- can momentarily be ≈ ±2π without normalization → head flicks). + while target_local > math.pi do target_local = target_local - 2 * math.pi end + while target_local < -math.pi do target_local = target_local + 2 * math.pi end -- Persistent state for slerp/rate-limit (carries angle across frames). local state = p.look_at_state[bid] diff --git a/manifest.lib b/manifest.lib index a7ec5bb..b8e52c1 100644 --- a/manifest.lib +++ b/manifest.lib @@ -1,6 +1,6 @@ { "id": "lib-core.puppet", - "version": "0.4.0", + "version": "0.4.1", "api_min": "0.1", "deps": [] }