Files
goodpuppies--petplay/classes/uiTextBatchTransforms.test.ts
mommysgoodpuppy 3f5e919698 Decoupled renderer: own process, tracking and present cadence
--webxr-decoupled-renderer moves raylib rendering out of the webxr worker
into an overlay_renderer child process (petplay/overlayRenderOwner.ts). The
worker extracts the scene and delivers it over the wire format in
overlaySceneWire.ts. Delivery is credit-based (overlaySceneDelivery.ts), and a
credit held more than a second is reclaimed, so a lost receipt can no longer
stall every scene. The worker skips extraction while every view's credits are
busy. The renderer paces itself, reads fresh HMD and controller poses, and
re-anchors tagged head, hand and ray subtrees (renderTrackingAnchor) to them,
so head and lasers stay smooth while the simulation stalls.

It presents in one of two modes, switchable at runtime with SETPRESENTMODE:
- projection: per-eye projection overlays published by a small native helper
  (native/overlayPresenter, built by `deno task overlay:presenter:build`).
  SteamVR reprojects them, but draws them behind every quad overlay,
  PetPlay's display screens included.
- panorama: the old head-locked stereo panorama. It sorts normally with the
  screens. Pacing and prediction stay live-tunable through SETRENDERERDEBUG,
  since swim and jitter are still being worked on. The default is
  frame-sync pacing with one extra frame of prediction.

Also: aim beam and cursor ignore depth so they stay over the screen they hit,
text batches compare world transforms instead of object identity,
projection-overlay docs and RE notes, a future plan for drawing the screens
inside the projection image, and an independence check script.

Agent: Claude Code 2.1.296; model claude-opus-5-5; thread c2136a88-9899-4b80-84e8-64fc160b5fd7
2026-10-15 21:49:40 +03:00

20 lines
898 B
TypeScript

import { captureTextBatchTransforms, textBatchTransformsMatch } from "./uiTextBatchTransforms.ts";
Deno.test("world-baked text cache invalidates when tracking mutates the same snapshot", () => {
const matrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
const texts = [{ worldMatrix: matrix }];
const cached = captureTextBatchTransforms(texts);
if (!textBatchTransformsMatch(texts, cached)) {
throw new Error("Unchanged stereo eye should reuse batch");
}
matrix[12] = .25;
if (textBatchTransformsMatch(texts, cached)) {
throw new Error("Tracked text reused stale world vertices");
}
const updated = captureTextBatchTransforms(texts);
if (!textBatchTransformsMatch(texts, updated)) {
throw new Error("Updated batch should be reusable for second eye");
}
if (cached[12] !== 0) throw new Error("Cache must own its transform snapshot");
});