BT410 Phase 5.3.6: look-button state machine -- full eyepoint composition
Reconstructs the binary's five-state LOOK machine (controls mapper tail, part_013.c:396-459) as proper members/methods: - MECHMPPR: LookState enum (None/Left/Right/Behind/Down) + lookState/ previousLookState (out of reserved[24] -> [22]). InterpretControls picks the state from the look buttons each frame and on a CHANGE calls Mech::CommitLookState. BT_FORCE_LOOK=<1..4> dev hook. - MECH: authored look angles lookLeft/Right/Front/BackAngle (deg->rad from the GameModel resource, guarded) + lookPitch/lookYaw + CommitLookState(int): side looks yaw by the authored angle, look-behind = yaw pi + lookBackAngle pitch, look-down = lookFrontAngle pitch, forward = identity. The per-frame eyepoint compose in Simulate adds the live Torso elevation on top. (reservedState [208] -> [202].) - Deferred inside the commit (needs MechWeapon viewFireEnable/rearFiring): per-view weapon fire re-arm + HUD pip group-mask flip. Verified headlessly: model reads clean authored angles (L=60 R=-60 F=-10 B=0 deg -- ModelResource layout confirmed again); BT_FORCE_LOOK=3 fires ONE commit ([look] state=3 yaw=3.14159 pitch=0) and the per-frame compose holds eyeYaw=pi with eyePitch=0.349066 (lookBackAngle + the 20deg-clamped elevation). Zero Fail. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -163,9 +163,20 @@ Mech::Mech(
|
||||
currentBodySpeed = 0.0f;
|
||||
|
||||
eyepointRotation = EulerAngles::Identity;
|
||||
lookPitch = 0.0f;
|
||||
lookYaw = 0.0f;
|
||||
|
||||
//
|
||||
// Look-view angles: defaults until the GameModel read below overrides them
|
||||
// with the authored per-mech values.
|
||||
//
|
||||
lookLeftAngle = 90.0f * RAD_PER_DEG;
|
||||
lookRightAngle = -90.0f * RAD_PER_DEG;
|
||||
lookFrontAngle = -30.0f * RAD_PER_DEG;
|
||||
lookBackAngle = 0.0f;
|
||||
|
||||
{
|
||||
for (int i = 0; i < 208; ++i)
|
||||
for (int i = 0; i < 202; ++i)
|
||||
{
|
||||
reservedState[i] = 0;
|
||||
}
|
||||
@@ -387,6 +398,10 @@ Mech::Mech(
|
||||
<< " maxAcc=" << model->maxAcceleration
|
||||
<< " throttleAdj=" << model->throttleAdjustment
|
||||
<< " (deg,deg,u/s^2,scale)" << endl << flush;
|
||||
DEBUG_STREAM << "[mech] look angles: L="
|
||||
<< model->lookLeftAngle << " R=" << model->lookRightAngle
|
||||
<< " F=" << model->lookFrontAngle << " B=" << model->lookBackAngle
|
||||
<< " (deg)" << endl << flush;
|
||||
}
|
||||
if (model->walkingTurnRate > 1.0f && model->walkingTurnRate < 360.0f)
|
||||
{
|
||||
@@ -404,6 +419,22 @@ Mech::Mech(
|
||||
{
|
||||
forwardThrottleScale = model->throttleAdjustment;
|
||||
}
|
||||
|
||||
//
|
||||
// The authored look-view angles (deg->rad), same insanity band
|
||||
// as the rest of the guarded reads.
|
||||
//
|
||||
{
|
||||
Scalar a;
|
||||
a = model->lookLeftAngle;
|
||||
if (a > -360.0f && a < 360.0f) lookLeftAngle = a * RAD_PER_DEG;
|
||||
a = model->lookRightAngle;
|
||||
if (a > -360.0f && a < 360.0f) lookRightAngle = a * RAD_PER_DEG;
|
||||
a = model->lookFrontAngle;
|
||||
if (a > -360.0f && a < 360.0f) lookFrontAngle = a * RAD_PER_DEG;
|
||||
a = model->lookBackAngle;
|
||||
if (a > -360.0f && a < 360.0f) lookBackAngle = a * RAD_PER_DEG;
|
||||
}
|
||||
}
|
||||
modelDesc->Unlock();
|
||||
}
|
||||
@@ -477,6 +508,67 @@ Joint*
|
||||
return joints->GetJoint(segment->GetJointIndex());
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
// CommitLookState -- the look-button eyepoint commit (the binary's five-state
|
||||
// look machine tail, controls mapper part_013.c:396-459). Re-aims the eyepoint
|
||||
// from the model's authored look angles: side looks yaw by lookLeft/RightAngle,
|
||||
// look-behind is yaw pi with lookBackAngle pitch, look-down pitches by
|
||||
// lookFrontAngle, forward is identity. The committed pitch/yaw are stored in
|
||||
// lookPitch/lookYaw so the per-frame compose in Simulate can keep adding the
|
||||
// live Torso elevation on top.
|
||||
//
|
||||
// Also part of the authentic commit, deferred to the weapon wave: re-arming
|
||||
// each weapon's view-fire enable (forward view = the non-rear-mounted weapons,
|
||||
// look-back = the rear-mounted ones, side/down = none) and flipping the HUD pip
|
||||
// group mask (forward = front group, look-back = rear group) -- both need the
|
||||
// MechWeapon viewFireEnable/rearFiring members, not yet reconstructed.
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
Mech::CommitLookState(int look_state)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
Scalar pitch = 0.0f;
|
||||
Scalar yaw = 0.0f;
|
||||
|
||||
switch (look_state)
|
||||
{
|
||||
case MechControlsMapper::LookLeftState:
|
||||
yaw = lookLeftAngle;
|
||||
break;
|
||||
case MechControlsMapper::LookRightState:
|
||||
yaw = lookRightAngle;
|
||||
break;
|
||||
case MechControlsMapper::LookBehindState:
|
||||
yaw = PI;
|
||||
pitch = lookBackAngle;
|
||||
break;
|
||||
case MechControlsMapper::LookDownState:
|
||||
pitch = lookFrontAngle;
|
||||
break;
|
||||
default:
|
||||
break; // LookNone: identity
|
||||
}
|
||||
|
||||
lookPitch = pitch;
|
||||
lookYaw = yaw;
|
||||
eyepointRotation = EulerAngles(
|
||||
Radian(Radian::Normalize(pitch)),
|
||||
Radian(Radian::Normalize(yaw)),
|
||||
Radian(0.0f)
|
||||
);
|
||||
|
||||
if (getenv("BT_MECH_LOG"))
|
||||
{
|
||||
DEBUG_STREAM << "[look] state=" << look_state
|
||||
<< " yaw=" << yaw << " pitch=" << pitch << endl << flush;
|
||||
}
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
// Simulate -- the mech's per-frame body Performance (the Mover locomotion tick).
|
||||
@@ -625,14 +717,12 @@ 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
|
||||
// the weapon boresight directly. Compose the committed look-state pitch/yaw
|
||||
// (CommitLookState, driven by the look buttons) with the Torso's live
|
||||
// currentElevation. DPLEyeRenderable / the aim ray read this each frame.
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
{
|
||||
Scalar lookPitch = 0.0f;
|
||||
Scalar lookYaw = 0.0f;
|
||||
Scalar elevation = 0.0f;
|
||||
if (sinkSourceSubsystem != NULL)
|
||||
{
|
||||
@@ -673,6 +763,7 @@ void
|
||||
<< " yaw=" << (Scalar)ypr.yaw
|
||||
<< " spd=" << currentBodySpeed
|
||||
<< " eyePitch=" << (Scalar)eyepointRotation.pitch
|
||||
<< " eyeYaw=" << (Scalar)eyepointRotation.yaw
|
||||
<< endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,6 +323,14 @@
|
||||
const EulerAngles&
|
||||
GetEyepointRotation() const { Check(this); return eyepointRotation; }
|
||||
|
||||
//
|
||||
// Look-state commit (called by the controls mapper on a look-button
|
||||
// state change): re-aim the eyepoint from the model's authored look
|
||||
// angles. look_state = MechControlsMapper::LookState.
|
||||
//
|
||||
void
|
||||
CommitLookState(int look_state);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Local Data
|
||||
//
|
||||
@@ -384,17 +392,28 @@
|
||||
Scalar currentBodySpeed;
|
||||
|
||||
//
|
||||
// Composed each frame in Simulate from the Torso elevation (+ the
|
||||
// look-state pitch/yaw once the look/eyepoint wave lands).
|
||||
// Composed each frame in Simulate: the look-state eye component
|
||||
// (lookPitch/lookYaw, set by CommitLookState from the authored look
|
||||
// angles) plus the Torso elevation.
|
||||
//
|
||||
EulerAngles eyepointRotation;
|
||||
Scalar lookPitch;
|
||||
Scalar lookYaw;
|
||||
|
||||
//
|
||||
// The model's authored look-view angles (rad; deg in the resource).
|
||||
//
|
||||
Scalar lookLeftAngle;
|
||||
Scalar lookRightAngle;
|
||||
Scalar lookFrontAngle;
|
||||
Scalar lookBackAngle;
|
||||
|
||||
//
|
||||
// Remaining per-frame targeting / animation state, advanced by the
|
||||
// mech2/mech3/mech4 simulation. Reserved until that path is
|
||||
// reconstructed with named fields.
|
||||
//
|
||||
int reservedState[208];
|
||||
int reservedState[202];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -286,6 +286,34 @@ wave (`BTCommitLookState`) is reconstructed.
|
||||
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).
|
||||
## PHASE 5.3 INCREMENT 6: the look-button state machine (2026-07-21)
|
||||
|
||||
The five-state LOOK machine (the binary's controls-mapper tail,
|
||||
part_013.c:396-459) is reconstructed as proper members/methods (not BT411's
|
||||
global bridges):
|
||||
|
||||
- **Mapper** (`MECHMPPR`): `LookState` enum (None/Left/Right/Behind/Down),
|
||||
`lookState`/`previousLookState` members; InterpretControls picks the state
|
||||
from the look buttons each frame and, ON A CHANGE, calls
|
||||
`mech->CommitLookState(state)`. `BT_FORCE_LOOK=<1..4>` dev hook.
|
||||
- **Mech**: authored look angles (`lookLeft/Right/Front/BackAngle`, deg→rad
|
||||
from the GameModel resource, guarded like the other reads) + `lookPitch`/
|
||||
`lookYaw` (the committed eye component) + **`CommitLookState(int)`** — side
|
||||
looks yaw by the authored angle, look-behind = yaw π + `lookBackAngle` pitch,
|
||||
look-down = `lookFrontAngle` pitch, forward = identity. The per-frame
|
||||
eyepoint compose in Simulate now adds the live Torso elevation on top of the
|
||||
committed look terms.
|
||||
- Deferred inside the commit (needs the MechWeapon viewFireEnable/rearFiring
|
||||
members): re-arming the per-view weapon fire enables (forward = non-rear
|
||||
weapons, look-back = rear-mounted 'b'-port weapons, side/down = none) and the
|
||||
HUD pip group-mask flip.
|
||||
|
||||
**VERIFIED headlessly:** the model reads clean authored angles (L=60° R=−60°
|
||||
F=−10° B=0° — layout confirmed again); `BT_FORCE_LOOK=3` fires ONE commit
|
||||
(`[look] state=3 yaw=3.14159 pitch=0`) and the per-frame compose holds
|
||||
`eyeYaw=π` with `eyePitch=0.349066` (lookBackAngle 0 + the 20°-clamped
|
||||
elevation). Zero Fail.
|
||||
|
||||
Next: the gait leg-clip animation / terrain drop / weapon wave. These become
|
||||
VISIBLE only under the renderer; headlessly the composed angles are loggable
|
||||
(as here).
|
||||
|
||||
@@ -119,8 +119,10 @@ MechControlsMapper::MechControlsMapper(
|
||||
displayMode = 0;
|
||||
pilotArrayPage = 0;
|
||||
pilotArray = 0;
|
||||
lookState = LookNone;
|
||||
previousLookState = LookNone;
|
||||
{
|
||||
for (int i = 0; i < 24; ++i)
|
||||
for (int i = 0; i < 22; ++i)
|
||||
{
|
||||
reserved[i] = 0;
|
||||
}
|
||||
@@ -193,6 +195,15 @@ void
|
||||
{
|
||||
stickPosition.y = (Scalar)atof(force_elev);
|
||||
}
|
||||
const char *force_look = getenv("BT_FORCE_LOOK");
|
||||
if (force_look != NULL)
|
||||
{
|
||||
int state = atoi(force_look);
|
||||
lookLeft = (state == (int)LookLeftState) ? 1 : 0;
|
||||
lookRight = (state == (int)LookRightState) ? 1 : 0;
|
||||
lookBehind = (state == (int)LookBehindState) ? 1 : 0;
|
||||
lookDown = (state == (int)LookDownState) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
Torso *torso = (Torso *)mech->GetTorsoSubsystem();
|
||||
@@ -271,6 +282,24 @@ void
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Look / eyepoint selection. Choose a look direction from the buttons;
|
||||
// when it changes, commit it -- the mech re-aims the eyepoint from its
|
||||
// authored look angles (and, once the weapon wave lands, re-arms the
|
||||
// per-view weapon fire enables through the same commit).
|
||||
//
|
||||
previousLookState = lookState;
|
||||
if (lookLeft > 0) lookState = LookLeftState;
|
||||
else if (lookRight > 0) lookState = LookRightState;
|
||||
else if (lookBehind > 0) lookState = LookBehindState;
|
||||
else if (lookDown > 0) lookState = LookDownState;
|
||||
else lookState = LookNone;
|
||||
|
||||
if (lookState != previousLookState)
|
||||
{
|
||||
mech->CommitLookState(lookState);
|
||||
}
|
||||
|
||||
if (getenv("BT_MECH_LOG"))
|
||||
{
|
||||
static Scalar reportAccum = 0.0f;
|
||||
|
||||
@@ -91,6 +91,21 @@
|
||||
VeteranMode
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Look states. A five-state machine off the pod's look buttons; on a state
|
||||
// change InterpretControls calls Mech::CommitLookState, which re-aims the
|
||||
// eyepoint from the model's authored look angles (and, once the weapon wave
|
||||
// lands, re-arms the per-view weapon fire enables).
|
||||
//
|
||||
public:
|
||||
enum LookState {
|
||||
LookNone = 0,
|
||||
LookLeftState,
|
||||
LookRightState,
|
||||
LookBehindState,
|
||||
LookDownState
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Construction and Destruction
|
||||
//
|
||||
@@ -158,7 +173,9 @@
|
||||
int displayMode;
|
||||
int pilotArrayPage;
|
||||
int pilotArray;
|
||||
int reserved[24];
|
||||
int lookState;
|
||||
int previousLookState;
|
||||
int reserved[22];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,11 +44,21 @@ torso twist (`SetAnalogTwistAxis`); Basic keeps the stick yaw as the leg turn.
|
||||
`Torso::TorsoSimulation` slews + clamps the elevation/twist (see TORSO.NOTES.md).
|
||||
Verified: `BT_FORCE_ELEV=0.8` → torsoElev clamps at the authentic 20° limit.
|
||||
|
||||
## Look-button state machine wired (2026-07-21)
|
||||
|
||||
The five-state LOOK machine is live: `LookState` enum + `lookState`/
|
||||
`previousLookState` members; each frame InterpretControls picks the state from
|
||||
the look buttons (left/right/behind/down, priority in that order) and on a
|
||||
CHANGE calls `Mech::CommitLookState(state)`, which re-aims the eyepoint from
|
||||
the mech's authored look angles (see MECH.NOTES.md increment 6).
|
||||
`BT_FORCE_LOOK=<1..4>` dev hook. Verified: look-behind commits yaw=π once and
|
||||
the per-frame eyepoint compose carries it with the live elevation.
|
||||
|
||||
## Deferred (the free-aim / camera wave)
|
||||
|
||||
Still not reconstructed: the HUD free-aim slew (`HUD::SetFreeAimSlew`, the
|
||||
Standard/Veteran torso-disabled path), the torso recenter command, and the
|
||||
look/eyepoint commit (`BTCommitLookState` — re-aims the eyepoint + re-arms the
|
||||
per-view weapon fire enables). These are the free-aim/camera surface; they come
|
||||
with the HUD/eyepoint wave. The skeleton-joint application of the torso angles
|
||||
is deferred with the render wave (TORSO.NOTES.md).
|
||||
weapon-side half of the look commit (per-view fire enables + HUD pip group
|
||||
mask — needs the MechWeapon viewFireEnable/rearFiring members). The
|
||||
skeleton-joint application of the torso angles is deferred with the render
|
||||
wave (TORSO.NOTES.md).
|
||||
|
||||
Reference in New Issue
Block a user