#!/usr/bin/env python3 """Wire Dave's dpl3-revive renderer into our LIVE running pod. Tails our device's VPX_FIFODUMP (VPXM records = the game's live VelociRender wire), feeds each message into Dave's VirtualBoard, and renders every draw_scene with his vrview software rasterizer in a real window -- using the game's own camera (the player's RIO input drives it). py live_bridge.py """ import os, sys, struct, time import numpy as np from _backend import pick_renderer from vrboard import VirtualBoard, Msg, A Renderer, backend = pick_renderer() path = sys.argv[1] board = VirtualBoard() board.munga = False r = Renderer(w=832, h=512, title=f"dpl3-revive renderer (Dave) -- LIVE from our pod [{backend}]") r.fps = int(os.environ.get('BRIDGE_FPS', '60' if backend == 'GL' else '30')) # eye height above the mech origin (cockpit). Mutable: UP/DOWN arrows = +-5, # LEFT/RIGHT = +-1, live (the render window must be focused). 35 was tuned # before the ground rendered and is way too high against real terrain. UPOFF = [float(os.environ.get('FP_UPOFF', '12'))] def fp_cam(board, cache): """First-person cockpit camera from the player vehicle's 0x1f pose: eye at the mech (+up), looking along its nose (+Z row), y-up world. Beats Dave's 11-DCS cam chain (which renders sky through our wire's convention).""" anim = board.anim_abs chain = cache.cam_chain h = None if chain and chain[-1] in anim: h = chain[-1] elif anim: h = max(anim, key=lambda k: float(np.abs(np.array(anim[k][9:12])).sum())) if h is None: return None f = anim[h] R = np.array(f[:9]).reshape(3, 3) t = np.array(f[9:12]) # look along the mech's travel direction. The +Z row rendered BACKWARD # (user: "geometry moving away as I drive"), so forward = -Z row. # FP_FWD_SIGN flips it back if needed. fwd = float(os.environ.get('FP_FWD_SIGN', '-1')) * R[2] n = np.linalg.norm(fwd) if n < 1e-6: return None fwd = fwd / n worldup = np.array([0.0, 1.0, 0.0]) eye = t + worldup * UPOFF[0] back = -fwd right = np.cross(worldup, back) rn = np.linalg.norm(right) if rn < 1e-6: return None right /= rn up = np.cross(back, right) # FP_RIGHT_SIGN=-1 mirrors the image X (verified: exact fliplr). Tried as a # yaw fix 2026-07-06 but the inverted-yaw report was about the NATIVE C++ # render, not this bridge -- the mirror just flipped the arena layout and # made the bridge yaw wrong too. Keep +1 (the validated look). right *= float(os.environ.get('FP_RIGHT_SIGN', '1')) M = np.eye(4) M[0, :3], M[1, :3], M[2, :3], M[3, :3] = right, up, back, eye return M def render(board): try: pg = r.pygame for ev in pg.event.get(): # drain before r.draw; tune eye height if ev.type == pg.QUIT: raise KeyboardInterrupt if ev.type == pg.KEYDOWN: step = {pg.K_UP: 5, pg.K_DOWN: -5, pg.K_RIGHT: 1, pg.K_LEFT: -1}.get(ev.key) if step: UPOFF[0] = max(0.0, UPOFF[0] + step) print(f"eye height = {UPOFF[0]:.0f}", flush=True) r.cache.maybe_rebuild(board) M = fp_cam(board, r.cache) if M is not None: r.cam_matrix = lambda _b, _M=M: _M r.draw(board) except KeyboardInterrupt: raise except Exception: pass print(f"waiting for {path} ...") while not os.path.exists(path): time.sleep(0.2) f = open(path, 'rb') print("tailing live wire -> Dave's renderer; drive the pod") pending = b'' frames = 0 last_report = time.time() while True: chunk = f.read(1 << 20) if chunk: pending += chunk off = 0 n = len(pending) while n - off >= 8: if pending[off:off + 4] != b'VPXM': off += 1 continue ln = struct.unpack_from('= 4: action = struct.unpack_from(' present a frame render(board) frames += 1 pending = pending[off:] if not chunk: try: r.pump() except KeyboardInterrupt: break except Exception: pass time.sleep(0.02) if time.time() - last_report > 4: last_report = time.time() print(f"frames={frames} nodes={len(board.nodes)} " f"uploads={len(board.uploads)} tex={len(board.tex)} " f"munga={board.munga} anim_abs={len(board.anim_abs)}")