Files
TeslaRel410/restoration/source410/BT/GYRO.NOTES.md
T
CydandClaude Fable 5 41fca98f85 BT410 5.3.110: the gyroscope lives -- the cockpit's springs, the hit bounce, and the crunch, all wired
The feel wave's cornerstone, transcribed from the task-#56 byte-exact donor
per the GYRO.NOTES.md plan:

  THE SPRINGS.  IntegrateEyeJoint (@004b2ec0): the eye TRANSLATION spring
  whose equilibrium (posSpring+negSpring)/2 IS the authentic steady eye
  offset, with the byte-verified quirks intact -- the damping step
  OVERWRITES the force accumulator (it carries last frame's damping and
  the damage impulses by design) and the position step has NO dt.
  IntegrateBody (@004b30ec): the body ROTATION spring, X/Z-crossed on the
  spring force and crossed AGAIN on the orientation step.

  THE SIM (@004b275c): chain the power watch (5.3.109's mirrors), slew the
  sway angle between the powered and impaired percentages -- impaired reads
  the gyro's OWN mirrored alarms: watchdog != Ready or heat == Failure --
  band-clamp, run both integrators.  The Performance ends there.

  THE JOINT WRITES (@004b33e0/@004b34ec) live where the binary calls them:
  the MECH master-perf tail after the gait pass, death-gated -- the idle
  sway onto the EyeJoint, and TRANSLATION <- eyePosition + ROTATION <-
  bodyOrientation onto 'jointeye', the BallTranslation joint the cockpit
  eyepoint rides.  Every write QuantiseEps-gated.

  THE HIT BOUNCE (@004b2980): every non-collision hit shakes the cockpit.
  Direction from the damage force (random horizontal when ~zero), rotated
  into the yaw-only torso frame, per-type priced amount/multiplier*response
  (Explosive alone reads burstCount), clamped 1.3 UPPER only, then the four
  kicks -- impulse, torque (which zeroes .y and negates itself), the fixed
  up-axis vibration, and the vertical mirror.  Fed from the damage hub's
  step 1, BEFORE zone resolution -- an invalid-zone hit still shakes you.

  THE CRUNCH: driving through a crushable prop now kicks the gyro (torque
  0.4 along the contact normal, upward impulse 0.2) -- the 5.3.102 staged
  site, closed.

Resource: the five DamageResponse quads {trans,pitchRoll,yaw,vibration}
appended after the multipliers (record 0x21C, binary-verified layout) --
they were always in the stream; we simply never read them.  The ctor now
zeroes every accumulator (the donor's history records a NaN poison from
exactly that omission), copies the clamp pairs (body doubled), self-points
externalPitchPtr at spare0 until a torso binds it, and REGISTERS the
Performance on the master -- it ticks live, no fault.

Stub census: 19 across 13 files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 16:42:56 -05:00

4.3 KiB

GYRO.CPP — reconstruction notes

Status: FULLY RECONSTRUCTED AND WIRED (2026-08-03). The simulation, both integrators, both joint writes, all four damage hooks, and the three feeds (damage hub, collision crunch, master-perf joint-write dispatch) are live; the registered Performance ticks without fault. Deep verification -- the visible cockpit bounce under fire -- is an operator/rig item. Donor: BT411 gyro.cpp (task #56 byte-exact).

Why this TU is the feel wave's cornerstone

The gyro owns the cockpit's physical feel: the eye TRANSLATION spring (the steady eye offset + hit bounce, written to the 'jointeye' BallTranslation joint that siteeyepoint rides) and the body ROTATION spring (the hull tip). The 5.3.99 collision block's staged "gyro crunch" feed and the damage hub's staged hit-bounce both land here.

The transcription plan (all donor line refs gathered 2026-08-03)

  1. Members (carve dynamicsState[64]): eyePosition/eyeVelocity/eyeForce/ eyeWork (Vector3D), bodyOrientation/bodyVelocity/bodyForce/bodyWork, swayAngle/swayBias/swayVelocity/swayActive, placeRot/placePos, workMatrix[12], externalPitchPtr (the torso-twist Scalar*), eyeJointNode/ mechJointNode (Joint*), damageResponse[5] {trans,pitchRoll,yaw,vibration}, vibrationDirection (fixed up axis). Clamps are ALIASES: eyeClampUpper == posSpring, eyeClampLower == negSpring; body likewise on the rotation pair.
  2. GyroscopeSimulation (@004b275c): PowerWatcher::Simulation(dt); the impaired pick (HeatModelOff || electrical != Ready || heat == FailureHeat) selects percentageOnDestruction vs Normal + swayBias as the sway target; slew by rotationPerSecond*dt with no-overshoot clamps, band-clamp into [minAnimationNoise, maxAnimationNoise]; IntegrateEyeJoint; IntegrateBody. The performance ENDS there — WriteEyeJoint/WriteMechJoint are called from the MECH master perf tail (@0x4aaf74/83), i.e. our Simulate gait seam, with the death/leg-anim gates.
  3. IntegrateEyeJoint (@004b2ec0, byte-exact): both spring terms use springConstant; damping OVERWRITES the force accumulator (carries into next frame by design); position += velocity with NO dt; per-axis clamp min-vs-posSpring then max-vs-negSpring.
  4. IntegrateBody (@004b30ec): same shape, three quirks — spring force X/Z-CROSSED (k.xd.z, k.yd.y, k.z*d.x); damping componentwise uncrossed; orientation += velocity CROSSED again (x+=v.z, z+=v.x). Clamp vs the rotation spring pair.
  5. WriteEyeJoint (@004b33e0): swayAngle onto the EyeJoint node — scalar channel scaled for hinge types <3, vector channel scaled for 4/5, write only past QuantiseEps. WriteMechJoint (@004b34ec): 'jointeye' type-5 ONLY: SetTranslation(eyePosition) + SetRotation(EulerAngles from bodyOrientation), each QuantiseEps-gated.
  6. Damage hooks: ApplyDamageImpulse (negate dir, *exageration, += eyeForce); ApplyDamageTorque (same into bodyForce, then bodyForce.y = 0, then whole-vector NEGATE); ApplyVerticalImpulse (x-only kick, .y mirrors .x). ApplyDamageResponse (@004b2980, byte-exact): no-op on Collision or zero amount; direction = damageForce or random-horizontal when ~0; rotate into the yaw-only torso frame (externalPitchPtr) and re-normalize; per-type scale amount/multiplier[type]*response[type].{4 terms} (Explosive alone multiplies burstCount); clamp each at 1.3 UPPER only; then the four kicks: impulse(dir,trans), torque(dir,pitchRoll), vibration along vibrationDirection, vertical(yaw term).
  7. Wiring: the damage hub's staged gyro feed (MECH.CPP TakeDamageMessageHandler step 1) calls ApplyDamageResponse; the crushable CRUNCH branch calls Torque(n,0.4)+Impulse(up,0.2) (already-shaped site); Simulate's gait seam calls WriteEyeJoint+WriteMechJoint on the master after the gait advances (death/leg gates per the binary tail).
  8. Family bridge: Mech::DistributeCollisionDamage already references Gyroscope::ClassDerivations directly — no ODR bridge needed in our tree.

Verification plan

BT_GYRO_LOG prints the joint writes + NaN sentinel; a live arena run with enemy fire should show [gyro-dmg] fan-outs and 'jointeye' translation motion on the wire (the cockpit eye rides it — visible as view bounce on hits).