← back to drive

PAXAL

/api/manifest

The JSON shape served at /arena/<scene>/manifest.json for chunked-streaming arenas. Authors of new arenas drop their .compressed.ply chunks + this file; the runtime discovers everything else. PRD §6.4.4. Validated at boot by lib/streaming/manifest.ts — payload-shape mismatches throw a ManifestValidationError and route the user back to title.

TOP LEVEL

version1Schema version. Currently always 1.
scene_idstringStable identifier for the scene (slug-friendly).
bounds{ min, max }Scene-wide AABB — min + max as [x,y,z]. Used for boot-time camera framing.
octree_depthnumberDepth of the octree split. Cosmetic — informational, not enforced.
mesh_proxy_urlstring.glb path for the hybrid render z-prepass + Rapier collision trimesh.
cubemap_urlstringPre-baked HDR cubemap path for vehicle PBR reflection (and the reflection probe).
chunksChunkEntry[]One entry per leaf chunk. Order is not significant; load priority is computed at runtime.

CHUNKENTRY

chunk_idstringStable id within the scene. Becomes the OPFS filename stem + the runtime entity name.
bounds{ center, radius }Bounding sphere — center [x,y,z] + radius. Used for distance-from-camera LOD picks.
aabb{ min, max }Axis-aligned bounding box. Used for tight frustum culling (sphere version overestimates).
variants{ [lod]: Variant }One variant per LOD ladder rung the chunk supports. Keys "0" / "1" / "2" / "3".

VARIANT

urlstringPath to the .compressed.ply binary. Relative to /arena/<scene>/ or the configured CDN base.
bytesnumberSize of the .ply blob. Used for the loading screen progress + bandwidth budgeting.
splat_countnumberGaussian-splat count after decoding. Used for in-HUD diagnostic readouts.

SAMPLE

{
  "version": 1,
  "scene_id": "room",
  "bounds": {
    "min": [-8.0, -3.8, -10.5],
    "max": [ 8.0,  4.2,  10.5]
  },
  "octree_depth": 2,
  "mesh_proxy_url": "/arena/room.collision.glb",
  "cubemap_url": "/arena/room-envmap.hdr",
  "chunks": [
    {
      "chunk_id": "c0_0_0",
      "bounds": { "center": [-4, 0, -5], "radius": 5.4 },
      "aabb":   { "min": [-8, -3, -10], "max": [0, 3, 0] },
      "variants": {
        "0": { "url": "c0_0_0.l0.compressed.ply", "bytes": 38400, "splat_count":  85000 },
        "1": { "url": "c0_0_0.l1.compressed.ply", "bytes": 92160, "splat_count": 210000 },
        "2": { "url": "c0_0_0.l2.compressed.ply", "bytes": 256000, "splat_count": 540000 }
      }
    }
  ]
}

AUTHORING WORKFLOW

  1. Capture your scene as a Gaussian splat (.compressed.ply). See /how-it-works for the engine pipeline.
  2. Run pnpm pipeline + pnpm split-by-scale to generate the LOD ladder + the octree split.
  3. Generate .collision.glb via npx splat-transform … -K.
  4. Drop the artefacts under public/arena/<scene>/ and add an entry to lib/arenas.ts.
  5. Calibrate spawnPos + floorY by booting + pressing [ / ] in-browser. SetplayRadius, fog, sunFlare to taste.