Death camera: forensics, capture, and probes (fix not yet applied)
Pilot sees the escape-pod/wreck interior at death instead of the portal ride. Findings (DEATH-SEQUENCE-NOTES.md): two death variants exist -- respawn deaths transit the chain camera to the portal at the origin (fp_cam's <100m vehicle-distance guard rejects exactly that ride = the fix target); mission-end deaths (tonight's capture) have no transit on the wire at all, just the fog fade at the wreck. At death the 0x1f articulation batches switch to driving origin-anchored nodes = the portal diorama animating; type-3 view flushes decode as projection+fog only (hither/yon at floats 12/13). Reference capture captures/netdeath-20260708.fifodump (full networked mission incl. death) + replay probes in probes/. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Type-3 (view) flush anatomy: are floats 0..13 a live camera pose?
|
||||
Sample across the whole mission + densely in the death tail; compare the
|
||||
candidate position triplet(s) against the vehicle root per frame."""
|
||||
import struct, os, sys
|
||||
sys.path.insert(0, r'c:\VWE\TeslaRel410\dpl3-revive\patha')
|
||||
import numpy as np
|
||||
|
||||
path = os.path.join(os.path.dirname(__file__), '..', 'captures', 'netdeath-20260708.fifodump')
|
||||
data = open(path, 'rb').read()
|
||||
|
||||
frames = 0
|
||||
created = {}
|
||||
veh = {} # latest max-translation 0x1f pose per frame
|
||||
flushes = [] # (frame, view_handle, floats24, veh_t)
|
||||
last_t = None
|
||||
o = 0
|
||||
while o + 8 <= len(data):
|
||||
if data[o:o+4] != b'VPXM':
|
||||
o += 1; continue
|
||||
ln = struct.unpack_from('<I', data, o+4)[0]
|
||||
if o + 8 + ln > len(data): break
|
||||
body = data[o+8:o+8+ln]; o += 8 + ln
|
||||
if len(body) < 4: continue
|
||||
a = struct.unpack_from('<I', body, 0)[0]
|
||||
p = body[4:]
|
||||
if a == 9:
|
||||
frames += 1
|
||||
elif a == 1 and len(p) >= 8:
|
||||
created[struct.unpack_from('<I', p, 4)[0]] = struct.unpack_from('<I', p, 0)[0]
|
||||
elif a == 0x1f and len(p) >= 8:
|
||||
# crude: largest |t| pose in the batch = player vehicle root
|
||||
n = struct.unpack_from('<I', p, 0)[0]
|
||||
off = 4
|
||||
best = None
|
||||
for _ in range(min(n, 64)):
|
||||
if off + 4 + 48 > len(p): break
|
||||
h = struct.unpack_from('<I', p, off)[0]
|
||||
f12 = struct.unpack_from('<12f', p, off + 4)
|
||||
t = f12[9:12]
|
||||
m = abs(t[0]) + abs(t[1]) + abs(t[2])
|
||||
if best is None or m > best[0]:
|
||||
best = (m, t)
|
||||
off += 4 + 48
|
||||
if best:
|
||||
last_t = best[1]
|
||||
elif a == 3 and len(p) >= 100:
|
||||
h = struct.unpack_from('<I', p, 0)[0]
|
||||
if created.get(h) == 3:
|
||||
flushes.append((frames, h, struct.unpack_from('<24f', p, 4), last_t))
|
||||
|
||||
print(f"draw frames={frames}, view flushes={len(flushes)}")
|
||||
handles = {}
|
||||
for f, h, fl, t in flushes:
|
||||
handles[h] = handles.get(h, 0) + 1
|
||||
print("view handles:", {hex(k): v for k, v in handles.items()})
|
||||
|
||||
def show(fr, h, fl, t):
|
||||
ts = "?" if t is None else f"({t[0]:7.1f},{t[1]:6.1f},{t[2]:7.1f})"
|
||||
print(f" f{fr} h={h:#x} veh={ts}")
|
||||
print(f" [0-8] " + " ".join(f"{x:7.3f}" for x in fl[0:9]))
|
||||
print(f" [9-13]" + " ".join(f"{x:9.2f}" for x in fl[9:14])
|
||||
+ f" [14-17] " + " ".join(f"{x:.2f}" for x in fl[14:18]))
|
||||
|
||||
# sparse samples through the mission
|
||||
print("\n-- sparse samples:")
|
||||
step = max(1, len(flushes) // 12)
|
||||
for i in range(0, len(flushes), step):
|
||||
show(*flushes[i])
|
||||
|
||||
# dense tail: last 30 flushes
|
||||
print("\n-- death tail (last 30):")
|
||||
for rec in flushes[-30:]:
|
||||
show(*rec)
|
||||
Reference in New Issue
Block a user