Files
CydandClaude Fable 5 0f5b2e28da Renderer: vendor live-bridge scripts; GPU backend unblocked (60fps)
- emulator/render-bridge/: the pod->Dave's-renderer live bridge (rescued
  from session scratchpad): live_bridge.py (first-person cam from the 0x1f
  pose, arrow-key eye-height trim), fp/chase offline renders, fifobridge,
  diagnostics, gauge_arena[_sound].conf, and launch_pod.ps1 (one-command
  pod+bridge restart: pentapus VPX_EXPLODE + AWE32 sound + GL bridge).
- _backend.py: renderer selection -- vrview_gl.GLRenderer (moderngl) by
  default, VRVIEW_SOFT=1 for the software reference; backend-agnostic
  frame save via last_frame.
- GPU backend runs on side-by-side CPython 3.13 (moderngl/glcontext cp313
  wheels; no MSVC needed): 63fps headless / 60.7 windowed vs 21fps software
  on the same scene, and the GL path also draws the vertex-alpha cloud dome.
- vrview.py: VRVIEW_GAMMA env selects DAC gamma (1.25 live-renderer legacy
  vs 1.7 per the original GAMMA.C) for A/B against the real pod.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:34:02 -05:00

46 lines
1.9 KiB
Python

import os, sys, 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, A
from vrview import Renderer
data = open(sys.argv[1], '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]; 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
r = Renderer(w=832, h=512); c = r.cache; c.maybe_rebuild(board)
anim = board.anim_abs; chain = c.cam_chain
h = chain[-1] if (chain and chain[-1] in anim) else \
max(anim, key=lambda k: float(np.abs(np.array(anim[k][9:12])).sum()))
mech = np.array(anim[h][9:12])
updir = float(sys.argv[3]) if len(sys.argv) > 3 else 1.0 # +1 or -1 for up axis
dist = float(sys.argv[4]) if len(sys.argv) > 4 else 900.0
# camera high above the mech, looking straight down; 'north' = +z as screen up
eye = mech + np.array([0.0, updir * dist, 0.0])
back = np.array([0.0, updir, 0.0]) # look -back = down
worldref = np.array([0.0, 0.0, 1.0])
right = np.cross(worldref, back); right /= max(np.linalg.norm(right), 1e-6)
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
# widen far clip so the whole area shows
if c.view 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, sys.argv[2])
print(f"wrote {sys.argv[2]} mech={mech.round(1)} eye={eye.round(1)} up={updir}")