BT410 5.3.67: pose_chase was upside down -- harness bug, wire exonerated

The operator caught it: the 5.3.65 image showed the mech hanging from its own
ground-shadow plate (-y is up in the bridge world).  The follow-up pinned down
what was and wasn't wrong, and the reconstruction survives untouched.

Right, by three independent wire-level proofs: MAD.SKL offsets are a coherent
Y-up model (hip +5.29, knees descending, torso ascending -- anatomical only
read +Y-up); the BGF vertex extents agree (foot meshes extend -1.0 below their
ankle to the sole, torso +3.8 up to the missile pods); and the SHIPPED pod's
wire carries the same signs (hip +6.21, knees negative, vehicle root a pure
yaw with det +1).  Our wire and shipped's are convention-identical -- no flip
exists between game and board in either game.

Wrong: the ad-hoc chase camera.  It borrowed the aerial up-hint from the
calibrated live-bridge world (where -y is up) and applied it to a raw
scene-space render of Y-up wire data; the symmetric checkerboard ground
disguised the inversion.  The shipped capture rendered upside-down through the
same harness, which is what cleared the wire.

Both conventions now documented in the roadmap: wire/scene space is Y-up in
both games; the live bridge presents -y-up via its calibrated mirror family
(FP_RIGHT_SIGN / CAGE_TWIST_SIGN, COCKPIT-CAGE-NOTES.md).

Tooling: pose_probe.py replaces the throwaway harness (updir=+1 scene space
default, -1 for the bridge sense).  pose_chase_upfixed.png is the corrected
milestone image: the MadCat right side up -- chicken-walker legs, purple knee
actuators, feet planted, shadow under the feet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-29 10:41:34 -05:00
co-authored by Claude Fable 5
parent 1233a1d5f6
commit f30acc6a94
3 changed files with 150 additions and 0 deletions
+37
View File
@@ -54,3 +54,40 @@ LOG: ISA Plug & Play BIOS enabled
LOG: VGA ROM BIOS init callback
LOG: pixratio 1.000, dw false, dh false
LOG: Aspect ratio: 640 x 480 xToY=1.333 yToX=0.750
LOG: WARNING: No translation support (to host) for code page 0
LOG: DOS keyboard layout loaded with main language code US for layout us
LOG: XMS: 50 handles allocated for use by the DOS environment
LOG: EMS page frame at 0xe000-0xefff
LOG: COMMAND.COM env size: 720 bytes
LOG: COMMAND.COM environment block: 0x0701 sz=0x002d
LOG: COMMAND.COM main body (PSP): 0x072f sz=0x009a
LOG: COMMAND.COM stack: 0x0749
LOG: pixratio 1.350, dw false, dh false
LOG: Aspect ratio: 720 x 540 xToY=1.333 yToX=0.750
LOG: SHELL:Redirect output to COM3
LOG: VPXLOG: fifosock client connected
VPX lights@f1: type6=0 typeE=0 decoded=0 dir=0 amb(0.00,0.00,0.00)
LOG: 237273074 ERROR MOUSE:Unhandled videomode 79 on reset
LOG: pixratio 1.000, dw false, dh false
LOG: Aspect ratio: 640 x 480 xToY=1.333 yToX=0.750
VPX lightnode t=6 nb=52: [8]00000000/0 [12]00000000/0 [16]00000001/1.4013e-45 [20]3f800000/1 [24]3f800000/1 [28]3f800000/1 [32]64078678/1e+22 [36]64078678/1e+22 [40]00311d60/4.51048e-39 [44]00326744/4.62882e-39 [48]ffffffff/nan
LOG: 684478479 ERROR INT10:PutPixel unhandled mode type 7
LOG: SHELL:Redirect output to RC.TXT
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:2 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:12 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:6 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:6 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:6 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:6 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:3 (IF0:0), TX:0, Break 0
LOG: Serial1: Errors: Framing 0, Parity 0, Overrun RX:6 (IF0:0), TX:0, Break 0
+72
View File
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""pose_probe -- offline chase render of the articulated mech in a fifodump.
py pose_probe.py <capture.fifodump> <out.png> [updir]
Frames the camera on the LAST-articulated root (board.anim_abs), a chase
offset away, and renders one frame. The proof harness for any "is the mech
posed/assembled right?" question -- offline, against a copy of the live dump,
zero interference with a running pod.
UP SENSE (updir, default +1): the wire's model/scene data is Y-UP -- proven
three ways on 2026-07-29: MAD.SKL offsets are anatomically coherent only with
+Y up (hip +5.29 above ground, knees/ankles descending), the BGF vertex
extents agree (foot meshes extend -1.0 below their ankle joint, torso +3.8
above shakey), and the SHIPPED pod's wire carries the same signs (hip +6.2,
knees negative, yaw-only vehicle root -- no flip anywhere on the wire). So a
scene-space render wants screen-up = +Y, which is updir=+1 here.
The LIVE bridge world is the other way around -- "-y is up here" -- because
the calibrated live path (fp_cam / the mirrored det -1 root-basis family,
FP_RIGHT_SIGN, COCKPIT-CAGE-NOTES.md) maps the wire into Dave's GL
presentation. The first version of this harness copied the aerial camera's
up hint from that world and rendered the mech hanging from its own shadow;
the operator caught it. updir=-1 reproduces that view if you ever need it.
"""
import sys, os, struct
sys.path.insert(0, r'C:\VWE\TeslaRel410\dpl3-revive\patha')
os.environ.setdefault('SDL_VIDEODRIVER', 'dummy')
import numpy as np
from vrboard import VirtualBoard, Msg
from vrview import Renderer
cap = sys.argv[1]
out = sys.argv[2] if len(sys.argv) > 2 else "pose_probe.png"
updir = float(sys.argv[3]) if len(sys.argv) > 3 else 1.0
data = open(cap, "rb").read()
board = VirtualBoard()
off = 0
while off + 8 <= len(data):
if data[off:off+4] != b'VPXM':
off += 1; continue
ln = struct.unpack_from('<I', data, off+4)[0]
body = data[off+8:off+8+ln]
if len(body) >= 4:
a = struct.unpack_from('<I', body, 0)[0]
if a < 0x100:
try: board.handle(Msg(False, 0xff, a, body[4:]))
except Exception: pass
off += 8 + ln
if not board.anim_abs:
print("no articulated roots in this capture"); sys.exit(1)
r = Renderer(w=832, h=512); c = r.cache; c.maybe_rebuild(board)
root = max(board.anim_abs.values(),
key=lambda f: float(np.abs(np.array(f[9:12])).sum()))
target = np.array(root[9:12]); target[1] += updir * 6.0 # mid-body
eye = target + np.array([30.0, updir * 14.0, 40.0]) # above + beside
fwd = target - eye; fwd /= np.linalg.norm(fwd); back = -fwd
right = np.cross([0.0, updir, 0.0], back); right /= np.linalg.norm(right)
up = np.cross(back, right)
M = np.eye(4); M[0,:3], M[1,:3], M[2,:3], M[3,:3] = right, up, back, eye
r.cam_matrix = lambda _b, _M=M: _M
if c.view is not None and c.view in board.nodes:
vb = bytearray(board.nodes[c.view].get('body') or b'')
if len(vb) >= 56:
struct.pack_into('<f', vb, 52, 1.0e6)
board.nodes[c.view]['body'] = bytes(vb)
r.draw(board)
r.pygame.image.save(r.screen, out)
print("wrote %s root at %s updir=%+g" % (out, target.round(1), updir))
@@ -1352,3 +1352,44 @@ ISR and LBE4ControlsManager are archive code, but the mapper (BT/MECHMPPR.CPP)
and the entire event/receiver plumbing (MUNGA/APP.CPP, RECEIVER.CPP) are ours.
RIO_TAP produced no file on this path -- byte-level dialogue comparison needs
a different tap point.
--------------------------------------------------------------------------------
CORRECTION FROM THE OPERATOR: pose_chase.png WAS UPSIDE DOWN -- HARNESS, NOT WIRE
--------------------------------------------------------------------------------
The operator caught it immediately ("-y is up here"): the 5.3.65 milestone
image showed the mech hanging from its own ground-shadow plate. The follow-up
established exactly what was and wasn't wrong, and the reconstruction survives
untouched:
WHAT IS RIGHT (three independent proofs, wire-level):
* MAD.SKL offsets are a coherent Y-UP model: hip +5.29 above ground, thigh
+0.24, knee -1.97 and ankle -2.39 descending, torso/missile mounts/eye
ascending. Anatomically consistent ONLY read +Y-up.
* The BGF vertex extents agree with the offsets: foot meshes extend -1.0
below their ankle joint (the sole), toe meshes -0.65 below their joints,
the torso mesh +3.8 above shakey (to the missile-pod tops), thigh meshes
reach down past the knee joint. One space, both data families.
* THE SHIPPED POD'S WIRE CARRIES THE SAME SIGNS. bt4.raw.bin's mech
skeleton: hip node (0,+6.21,0), knees negative, paired thighs +/-1.71,
and the vehicle root (df1) is a PURE YAW (+1 on the Y diagonal, det +1) at
its world position -- no flip anywhere between game and board, in either
game. Our wire and shipped's are convention-identical.
WHAT WAS WRONG: the ad-hoc chase camera in the 5.3.65 render. It borrowed
fifobridge's aerial up-hint ([0,-1,0], correct for the calibrated LIVE-bridge
world where -y is up) and applied it to a raw scene-space render of Y-up wire
data -- screen-up landed on model-down, mech hangs from its shadow, and the
symmetric checkerboard ground disguised it. The shipped capture rendered
upside-down through the same harness, which is what cleared the wire.
THE TWO CONVENTIONS, so nobody trips on this again:
* WIRE / scene space: Y-UP. Both games, models and skeletons alike.
* LIVE bridge presentation: -y is up. The calibrated path (fp_cam, the
mirrored det -1 root basis, FP_RIGHT_SIGN / CAGE_TWIST_SIGN family) maps
between them; COCKPIT-CAGE-NOTES.md documents that machinery.
TOOLING: pose_probe.py replaces the throwaway harness -- updir=+1 default
(scene space), updir=-1 reproduces the bridge-world sense. Verified:
pose_chase_upfixed.png shows the MadCat right side up -- chicken-walker legs,
purple knee actuators, feet planted, shadow quad UNDER the feet, weapon-pod
arms. The milestone stands, now with the correct picture.