From 87b1c048cf99a1843e1264d3753449e8005493f5 Mon Sep 17 00:00:00 2001 From: Cyd Date: Tue, 21 Jul 2026 21:51:28 -0500 Subject: [PATCH] BT410 Phase 5.3.5: eyepointRotation -- torso elevation pitches the eye/aim-ray, not a joint Investigated the next planned binding (elevation -> gun joints jointlgun/ jointrgun) before implementing it, and found it was the wrong target: BT411's own reverse-engineering history records that NO gun/arm elevation joint exists in the authentic engine. The pod's stick-Y aim pitches the COCKPIT EYE and the weapon boresight directly (mech4.cpp @~5219, pixel-calibrated against real screenshots) -- the torso geometry never tilts for elevation on this mech family. Reconstructing a gun-joint binding would have been invented behavior. - MECH.HPP: EulerAngles eyepointRotation member (out of reservedState, now [208]) + GetEyepointRotation() accessor. - MECH.CPP: composed each frame in Simulate -- eyepointRotation = EulerAngles(Radian(Normalize(lookPitch+elevation)), Radian(Normalize(lookYaw)), Radian(0)), reading Torso::CurrentElevation() via sinkSourceSubsystem. lookPitch/lookYaw are 0 until the look-button wave (BTCommitLookState) lands. Verified: BT_FORCE_ELEV=0.8 -> torsoElev and eyePitch both read 0.349066 (the authentic 20 degree resource limit) every frame, exact match; neutral -> 0. Zero Fail. Corrected TORSO.NOTES.md's prior (wrong) "next: gun joints" note. Co-Authored-By: Claude Fable 5 --- restoration/source410/BT/MECH.CPP | 30 ++++++++++++++++++++- restoration/source410/BT/MECH.HPP | 24 ++++++++++++++++- restoration/source410/BT/MECH.NOTES.md | 35 +++++++++++++++++++++---- restoration/source410/BT/TORSO.NOTES.md | 21 ++++++++++----- 4 files changed, 96 insertions(+), 14 deletions(-) diff --git a/restoration/source410/BT/MECH.CPP b/restoration/source410/BT/MECH.CPP index e72ef3e7..72a9caa5 100644 --- a/restoration/source410/BT/MECH.CPP +++ b/restoration/source410/BT/MECH.CPP @@ -162,8 +162,10 @@ Mech::Mech( bodyTargetSpeed = 0.0f; currentBodySpeed = 0.0f; + eyepointRotation = EulerAngles::Identity; + { - for (int i = 0; i < 211; ++i) + for (int i = 0; i < 208; ++i) { reservedState[i] = 0; } @@ -618,6 +620,31 @@ void } } + // + //----------------------------------------------------------------------- + // Eyepoint / aim-ray composition (mech4.cpp @~5219, pixel-calibrated in the + // BT411 reverse-engineering). The pilot's torso-elevation aim does NOT tilt + // any skeleton joint on this mech family -- it pitches the cockpit eye and + // the weapon boresight directly. Compose the look-state pitch/yaw (0 until + // the look/eyepoint wave reconstructs BTCommitLookState) with the Torso's + // currentElevation. DPLEyeRenderable / the aim ray read this each frame. + //----------------------------------------------------------------------- + // + { + Scalar lookPitch = 0.0f; + Scalar lookYaw = 0.0f; + Scalar elevation = 0.0f; + if (sinkSourceSubsystem != NULL) + { + elevation = ((Torso *)sinkSourceSubsystem)->CurrentElevation(); + } + eyepointRotation = EulerAngles( + Radian(Radian::Normalize(lookPitch + elevation)), + Radian(Radian::Normalize(lookYaw)), + Radian(0.0f) + ); + } + // //----------------------------------------------------------------------- // Integrate position and commit the Origin to the world transform. @@ -645,6 +672,7 @@ void << localOrigin.linearPosition.z << ")" << " yaw=" << (Scalar)ypr.yaw << " spd=" << currentBodySpeed + << " eyePitch=" << (Scalar)eyepointRotation.pitch << endl << flush; } } diff --git a/restoration/source410/BT/MECH.HPP b/restoration/source410/BT/MECH.HPP index ffa609d2..db72d5df 100644 --- a/restoration/source410/BT/MECH.HPP +++ b/restoration/source410/BT/MECH.HPP @@ -51,6 +51,10 @@ # include # endif +# if !defined(ROTATION_HPP) +# include +# endif + //##################### Forward Class Declarations ####################### class Mech; class Subsystem; @@ -307,6 +311,18 @@ Scalar GetForwardThrottleScale() const { Check(this); return forwardThrottleScale; } void SetForwardThrottleScale(Scalar s){ Check(this); forwardThrottleScale = s; } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Eyepoint / aim-ray composition. The pilot's torso-elevation aim (stick + // pitch) does NOT tilt any skeleton joint on this mech family -- it pitches + // the COCKPIT EYE and the weapon boresight (pixel-calibrated in the BT411 + // reverse-engineering: "pitch does not work" turned out to mean nothing + // consumed Torso's currentElevation, not that a joint was un-animated). + // Composed each frame in Simulate; DPLEyeRenderable / the aim ray read it. + // + public: + const EulerAngles& + GetEyepointRotation() const { Check(this); return eyepointRotation; } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Local Data // @@ -367,12 +383,18 @@ Scalar bodyTargetSpeed; Scalar currentBodySpeed; + // + // Composed each frame in Simulate from the Torso elevation (+ the + // look-state pitch/yaw once the look/eyepoint wave lands). + // + EulerAngles eyepointRotation; + // // Remaining per-frame targeting / animation state, advanced by the // mech2/mech3/mech4 simulation. Reserved until that path is // reconstructed with named fields. // - int reservedState[211]; + int reservedState[208]; }; #endif diff --git a/restoration/source410/BT/MECH.NOTES.md b/restoration/source410/BT/MECH.NOTES.md index dfe4e339..fff41969 100644 --- a/restoration/source410/BT/MECH.NOTES.md +++ b/restoration/source410/BT/MECH.NOTES.md @@ -259,8 +259,33 @@ drop, torso/free-look aiming (Torso/HUD analog axes), telemetry filters. (`horizJoint=''`, `enabled=0`) so its twist path is inert — correct and guarded; a torso-twist mech would drive the joint. -Next joint piece: elevation → the gun joints (`jointlgun`/`jointrgun`) — the -aim mechanism for fixed-torso mechs — which needs the weapon-joint binding -(resolved from the weapon subsystems, not the torso resource). Then the gait -leg-clip animation. Both become VISIBLE only under the renderer; headlessly the -joint transforms are computable/loggable. +## PHASE 5.3 INCREMENT 5: eyepointRotation -- elevation is NOT a gun-joint binding (2026-07-21) + +Before reconstructing "elevation → gun joints," checked BT411 for how the +authentic engine actually consumes `Torso::currentElevation` — and it does NOT +drive any skeleton joint. BT411's own history records the discovery (mech4.cpp +@~5219, user report "pitch does not work"): the Torso sim integrated the R/F +aim into `currentElevation` but nothing consumed it — no joint search ever +existed for a gun/arm elevation joint. **The pod's stick-Y aim pitches the +COCKPIT EYE, not the torso geometry**; `eyepointRotation` (an `EulerAngles` +Mech member) is composed each frame from the look-state pitch/yaw (buttons) +plus the Torso elevation, and `DPLEyeRenderable` reads it for both the camera +view AND the weapon boresight (so a low target can still be hit — the fire ray +re-applies the elevation onto the leveled boresight). BT411's sign convention +was pixel-calibrated against real screenshots; our composition matches it +verbatim (mirroring the additive pitch, zero look terms until that wave lands). + +**Reconstructed:** `Mech::eyepointRotation` (`EulerAngles`, out of `reservedState`, +now `[208]`) + `GetEyepointRotation()` accessor. Composed in `Simulate` each +frame: `eyepointRotation = EulerAngles(Radian(Normalize(lookPitch + elevation)), +Radian(Normalize(lookYaw)), Radian(0))`, reading `Torso::CurrentElevation()` via +`sinkSourceSubsystem`. `lookPitch`/`lookYaw` are 0 until the look/eyepoint button +wave (`BTCommitLookState`) is reconstructed. + +**VERIFIED headlessly:** `BT_FORCE_ELEV=0.8` → `torsoElev=0.349066` (the 20° +resource limit) and `eyePitch=0.349066` — an exact match, every frame; neutral → +`eyePitch=0`. Zero Fail. + +Next: the look-button wave (`BTCommitLookState`, `gBTLookPitch/Yaw`) to compose +the full eyepoint; then the gait leg-clip animation. Both become VISIBLE only +under the renderer; headlessly the composed angles are loggable (as here). diff --git a/restoration/source410/BT/TORSO.NOTES.md b/restoration/source410/BT/TORSO.NOTES.md index f52858b8..60decba5 100644 --- a/restoration/source410/BT/TORSO.NOTES.md +++ b/restoration/source410/BT/TORSO.NOTES.md @@ -37,12 +37,19 @@ its twist path is inert — correctly guarded (null joint → no apply, no crash torso-twist mech drives the joint. Verified headlessly; the VISUAL rotation needs the renderer. +## Elevation does NOT drive a gun joint (corrected 2026-07-21) + +Checked BT411 before reconstructing a "gun-elevation joint": no such joint +binding exists anywhere in the authentic engine. `currentElevation` instead +composes into `Mech::eyepointRotation` (the cockpit-eye / weapon-boresight +pitch) — see MECH.NOTES.md "PHASE 5.3 INCREMENT 5". `TorsoSimulation` only +needed to keep advancing the scalar state, which it already did; the missing +piece was the CONSUMER (`Mech::Simulate`'s eyepoint composition), now +reconstructed and verified (`torsoElev` == `eyePitch` every frame). + ## Deferred -- **Elevation → gun joints.** This mech aims by pitching the guns - (`jointlgun`/`jointrgun`), not twisting the torso. `currentElevation` still - only advances the scalar state; applying it to the gun joints needs the - weapon-joint binding (resolved from the weapon subsystems, not the torso - resource) — the next joint piece. -- HUD free-aim slew, look/eyepoint commit, `TorsoCopySimulation` (replicant - console-driven aim) — still staged. +- HUD free-aim slew, the look-button state machine (`BTCommitLookState` / + `gBTLookPitch`/`gBTLookYaw` — composes with elevation into the full + eyepoint), `TorsoCopySimulation` (replicant console-driven aim) — still + staged.