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 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-21 21:51:28 -05:00
co-authored by Claude Fable 5
parent 9fff0e969e
commit 87b1c048cf
4 changed files with 96 additions and 14 deletions
+29 -1
View File
@@ -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;
}
}
+23 -1
View File
@@ -51,6 +51,10 @@
# include <namefilt.hpp>
# endif
# if !defined(ROTATION_HPP)
# include <rotation.hpp>
# 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
+30 -5
View File
@@ -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).
+14 -7
View File
@@ -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.