tfrere HF Staff Cursor commited on
Commit
accdb25
·
1 Parent(s): 7f27f34

fix: freeze chase-cam heading during rolls and kicks

Browse files

The trunk tumbles through a roll (and shakes during kicks), so the yaw
extracted from its quaternion spins wildly and whipped the chase camera
around. The chase now lazily latches the last healthy yaw and holds it
for the whole one-shot; position/target easing still follows the trunk.
No timers: both one-shots deterministically hand back to walk, where
live yaw tracking resumes and the position lerp absorbs the small
heading correction. Measured over a full roll: 180 deg trunk-yaw
excursion, 0.2 deg camera azimuth swing.

Cache-buster bumped to 28.

Co-authored-by: Cursor <cursoragent@cursor.com>

Files changed (2) hide show
  1. index.html +1 -1
  2. rl.js +18 -4
index.html CHANGED
@@ -476,7 +476,7 @@
476
  appended: a plain src attribute can 401 when the browser blocks the
477
  *.static.hf.space auth cookie inside the hub iframe. -->
478
  <script type="module">
479
- const V = "27"; // bump on rl.js changes to defeat heuristic caching
480
  const sign = new URLSearchParams(location.search).get("__sign");
481
  const suffix = sign ? `&__sign=${encodeURIComponent(sign)}` : "";
482
  import(`./rl.js?v=${V}${suffix}`);
 
476
  appended: a plain src attribute can 401 when the browser blocks the
477
  *.static.hf.space auth cookie inside the hub iframe. -->
478
  <script type="module">
479
+ const V = "28"; // bump on rl.js changes to defeat heuristic caching
480
  const sign = new URLSearchParams(location.search).get("__sign");
481
  const suffix = sign ? `&__sign=${encodeURIComponent(sign)}` : "";
482
  import(`./rl.js?v=${V}${suffix}`);
rl.js CHANGED
@@ -627,13 +627,27 @@ const CHASE_PITCH = 0.42; // rad above horizontal, keeps the floor in view
627
  const CHASE_EASE = 0.05; // exponential ease, cinematic on turns
628
  const _chasePos = new THREE.Vector3();
629
  const _chaseDir = new THREE.Vector3();
 
 
 
 
 
 
 
 
630
  function updateChaseCam() {
631
  if (!chaseCam) return;
632
  const qpos = data.qpos;
633
- const yaw = Math.atan2(
634
- 2 * (qpos[3] * qpos[6] + qpos[4] * qpos[5]),
635
- 1 - 2 * (qpos[5] * qpos[5] + qpos[6] * qpos[6]),
636
- );
 
 
 
 
 
 
637
  const dist = camera.position.distanceTo(controls.target);
638
  const horiz = dist * Math.cos(CHASE_PITCH);
639
  const vert = dist * Math.sin(CHASE_PITCH);
 
627
  const CHASE_EASE = 0.05; // exponential ease, cinematic on turns
628
  const _chasePos = new THREE.Vector3();
629
  const _chaseDir = new THREE.Vector3();
630
+ // During one-shot rolls and kicks the trunk tumbles, so the yaw read from
631
+ // its quaternion spins wildly and would whip the camera around. Lazily
632
+ // latch the last healthy yaw while walking/sitting and hold it for the
633
+ // whole one-shot; the position/target easing keeps following the trunk.
634
+ // No timers needed: both one-shots deterministically hand back to walk,
635
+ // and the camera position lerp absorbs the small heading correction when
636
+ // live tracking resumes (rolls end facing roughly the same way).
637
+ let chaseHeldYaw = 0;
638
  function updateChaseCam() {
639
  if (!chaseCam) return;
640
  const qpos = data.qpos;
641
+ let yaw;
642
+ if (mode === "roll" || isKick()) {
643
+ yaw = chaseHeldYaw;
644
+ } else {
645
+ yaw = Math.atan2(
646
+ 2 * (qpos[3] * qpos[6] + qpos[4] * qpos[5]),
647
+ 1 - 2 * (qpos[5] * qpos[5] + qpos[6] * qpos[6]),
648
+ );
649
+ chaseHeldYaw = yaw;
650
+ }
651
  const dist = camera.position.distanceTo(controls.target);
652
  const horiz = dist * Math.cos(CHASE_PITCH);
653
  const vert = dist * Math.sin(CHASE_PITCH);