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>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Phase 1 core: feed OUR emulator's VPX_FIFODUMP (VPXM records = our game's
|
||||
live VelociRender wire) into the friend's virtual board + renderer. Proves our
|
||||
wire drives their renderer with no rebuild. Offline here; live = tail the file.
|
||||
|
||||
py fifobridge.py <file.fifodump> <out.png> [distmul]
|
||||
"""
|
||||
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
|
||||
|
||||
cap = sys.argv[1]
|
||||
out = sys.argv[2] if len(sys.argv) > 2 else 'fifobridge.png'
|
||||
distmul = float(sys.argv[3]) if len(sys.argv) > 3 else 1.4
|
||||
|
||||
VALID = set(int(a) for a in A)
|
||||
|
||||
def records(data):
|
||||
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]
|
||||
yield data[off+8:off+8+ln]
|
||||
off += 8 + ln
|
||||
|
||||
data = open(cap, 'rb').read()
|
||||
board = VirtualBoard()
|
||||
nrec = nfed = nskip = nerr = 0
|
||||
for body in records(data):
|
||||
nrec += 1
|
||||
if len(body) < 4:
|
||||
continue
|
||||
action = struct.unpack_from('<I', body, 0)[0]
|
||||
if action >= 0x100: # init-arg string / non-message bursts
|
||||
nskip += 1; continue # (real actions are all < 0x100, incl.
|
||||
# the unnamed game ones: 0x1f, 0x2d...)
|
||||
try:
|
||||
board.handle(Msg(False, 0xff, action, body[4:]))
|
||||
nfed += 1
|
||||
except Exception:
|
||||
nerr += 1
|
||||
print(f'records={nrec} fed={nfed} skipped={nskip} errs={nerr}')
|
||||
print(f'nodes={len(board.nodes)} geom={len(board.geom)} tex={len(board.tex)} '
|
||||
f'anim_abs={len(getattr(board,"anim_abs",{}))} munga={getattr(board,"munga",None)}')
|
||||
|
||||
r = Renderer(w=832, h=512)
|
||||
r.cache.maybe_rebuild(board)
|
||||
c = r.cache
|
||||
print(f'instances={len(c.instances)}')
|
||||
|
||||
# synthetic aerial camera framing all decoded geometry + lift far clip
|
||||
mins = np.array([np.inf]*3); maxs = np.array([-np.inf]*3); nv = 0
|
||||
for inst in c.instances:
|
||||
M = r.chain_matrix(board, inst['chain'])
|
||||
for gh in inst['geoms']:
|
||||
mesh = c._mesh(board, gh)
|
||||
if not mesh or 'pos' not in mesh or len(mesh['pos']) == 0:
|
||||
continue
|
||||
pw = mesh['pos'] @ M[:3, :3] + M[3, :3]
|
||||
mins = np.minimum(mins, pw.min(0)); maxs = np.maximum(maxs, pw.max(0)); nv += len(pw)
|
||||
if not np.isfinite(mins).all():
|
||||
print('NO renderable geometry'); sys.exit(1)
|
||||
center = (mins+maxs)/2; radius = float(np.linalg.norm(maxs-mins)/2) or 400.0
|
||||
print(f'bounds min={mins.round(1)} max={maxs.round(1)} center={center.round(1)} radius={radius:.1f} verts={nv}')
|
||||
|
||||
eye = center + np.array([radius*0.5, -radius*0.8, radius*distmul])
|
||||
fwd = center - eye; fwd /= np.linalg.norm(fwd); back = -fwd
|
||||
right = np.cross([0.0,-1.0,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', out)
|
||||
Reference in New Issue
Block a user