// Platform

The two engines that power every report.

Every visualization in Traced — heatmaps, kill links, view cones, player paths, scoped reports — runs on one of two engines. Understanding what they do and how to tune them helps you make the dashboard read clearly for your team.

Spatial Density

Input: a stream of (x, y, z) positions from events.
Output: 3D heatmap of clustered spheres, color-graded by density.

Algorithm

  1. Spatial binning. The world is partitioned into uniform cubic cells (default 1.6m on a side, tunable). Each event lands in exactly one cell.
  2. Aggregation. For each occupied cell we compute the centroid (average position of all events in the cell) and a density score.
  3. Normalization. Scores are divided by the max score and raised to the 0.6 power, which compresses the bright tail so a single hot cell doesn't wash out everything else.
  4. Threshold. Cells below minDensity (default 5%) are hidden — keeps the viewer from rendering thousands of noise spheres.
  5. Color + size. Surviving cells render as spheres whose color interpolates over the heat gradient (cold blue → purple → orange → yellow) and whose radius grows with density.

Uniqueness weighting

Off by default it would be density = count of events in cell. One AFK bot looping in a corner spawns a fake hotspot. Uniqueness weighting (default ON) instead uses density = √(distinct sessions) × event_count. A cell touched by 50 sessions ranks higher than a cell hit 500 times by one session — better signal for real game balance.

Tuning

SettingDefaultWhen to change
cellSize1.6mSmall for fine detail in tight maps, larger for top-down overviews of big arenas.
minDensity0.05Raise to hide noise; lower if hotspots are disappearing under heavier traffic.
sphereScale1.0×Cosmetic. Bump up for screenshots.
uniquenessWeightedonTurn off if you want raw event-volume hotspots (e.g., damage-dealt analysis where many shots per session is the signal).

Path Flow

Input: position_samples rows grouped by (session_id, player_id).
Output: smooth curves showing each player's trajectory through the level.

Algorithm

  1. Group + sort. Samples are bucketed by (session, player) and sorted by timestamp.
  2. Decimation. Chains longer than 500 samples are stride-sampled to 500. The Catmull-Rom interpolation in the next step hides the gaps.
  3. Curve fit. A 3D Catmull-Rom curve runs through the samples, producing a smooth path even when the underlying TrackPosition calls are spaced out (default 10/sec).
  4. Coloring. Each chain gets a unique hue from the teal→cyan band (so different players are distinguishable) with additive blending so overlapping paths brighten naturally.

Tuning + cost

Position streams are the highest-volume table in the system — typically 10 rows/second per player. Traced rate-limits client-side via MaxPositionSamplesPerSecond on the SDK config. Server-side limits are tier-based; future Pro tier caps position storage at 30 days by default.

For high-fidelity capture, drop MaxPositionSamplesPerSecond to match your VR frame rate (e.g., 72 for Quest, 90 for PCVR). For analytics-only use cases, 5-10/sec is usually enough — Catmull-Rom hides the gaps and the storage cost drops by 10×.

Reports = templates over engines

Death Heatmap, Combat Hotspots, Player Paths — these aren't separate code. They're JSON configs that parameterize one of the engines with a filter, an accent color, and an icon. Adding a new template is a config entry, not a viewer change.

See the architecture overview for the full data flow, or the SDK reference for the call signatures that feed both engines.

Performance budget

  • Heatmap rebuild — O(N) in event count. 5,000 events → ~120 cells → 16ms typical.
  • Path-flow rebuild — O(N) in sample count after decimation. 5,000 samples → ~80ms.
  • Render loop — fixed cost per visible sphere/line, runs in WebGL. Typical session: 60fps on integrated GPUs.

If the viewer drops below 30fps for you on a typical project, file an issue — it's a regression on our side. The viewer is designed to handle 50,000+ events without breaking a sweat.