mappy

mappy · utilities · schema v1

MAPPY is a multi-surface manual projection mapper. It spawns up to six surfaces; each surface is fed by a distinct video input (in1in6), warped onto its own draggable quad in the output frame, and composited — painter's order, OVER — into one video output you send to a projector.

model

  • One surface — de-skew. Point a projector at an awkwardly-angled wall, then drag a surface's four corners until the projected image lines up square. The homography corrects the keystone / perspective distortion.
  • Up to six — map a cube (or a stage set). Give each face of a white cube its own feed; only ~3-4 faces are ever visible from one projector angle, so six surfaces cover a rotating object or a multi-panel set. Composite order (in1 first … in6 last) lets a later surface paint over an earlier one where they overlap.
  • Manual only (v1). You align by hand on the card. The camera-assisted auto-align — point a camera at the projection and solve the homography from detected features — is a later phase. There is no camera input and no CV in v1 by design.

warp + composite

Every surface owns a four-corner quad in normalized [0,1] output space, corner order TL, TR, BR, BL. A homography (the unit square → that quad) defines the projective warp. The shader runs per output texel: it takes the output uv, applies the inverse homography to find the matching source uv, and samples the input there — only where the source uv is inside [0,1] (outside, the texel is transparent so the layers beneath show through). The pure 2D projective math (DLT solve · apply · invert · column-major-for-GLSL) lives in $lib/video/mappy-homography and is shared by the shader and the unit tests.

sourceunit squarehomographyoutput (draggable quad)

Surfaces composite in input order with an OVER blend. The composite is exposed on the out port and as the on-card live preview.

Grids-first. A fresh MAPPY shows one surface, and a live surface with no input connected renders its numbered calibration grid — a per-surface-tinted checker + bright border + cross-hairs + a big seven-segment digit naming the input that will feed it. So with nothing patched the output is the grid(s): set the geometry up on the physical faces first (drag corners; use +/ to add up to six surfaces), then connect video. The instant inN is connected, surface N swaps grid → warped video in the quad you already mapped — surface ↔ input is fixed, no reassignment. The GRID toggle forces the grid back on for every live surface (a re-alignment override); connecting inN auto-activates surface N even beyond the count.

card & MAP editor

The card has a live composite preview with draggable corner handles + quad outlines (coloured per surface), a +/ surface counter, a MAP button, the GRID toggle, and a per-surface legend (focus · FIT/CROP · reset · a ● video / ○ grid state). Drag a corner to pin it, or grab the surface's interior and drag to move the whole quad bodily — on the card preview and in the editor. Precise corner-pin work happens in the MAP editor — a full-window canvas with big handles, drag-inside-a-surface to move it bodily, surface tabs, a per-surface FIT/CROP toggle, and snap-to-grid for matching a real edge. All ports live on the yellow drill-down patch panel — no raw side jacks.

FIT vs CROP (per surface)

Each surface has its own FIT toggle (default ON; surfaces are independent). It is one cheap per-surface shader uniform — no extra render pass, no readback.

  • FIT (default) — zoom-fit. The homography squeezes the whole source [0,1]² into the dragged quad. Resize the box and the entire frame stretches to fill it (the original behaviour).
  • CROP — window at native scale. The quad becomes a moveable window onto the source, which is pinned 1:1 into output space: moving the box pans across the natively-placed source, and resizing it crops more or less. The quad still provides the shape/mask — only the part of the source under the box shows. Use it to frame a region of a feed onto a physical panel without distorting it.

inputs

idcable
in1video
in2video
in3video
in4video
in5video
in6video

outputs

idcable
outvideo

params

idlabelrangedefault
showGridGrid0..10
surfaceCountSurfaces1..61

usage

  1. Route out → OUTPUT (your projector). With nothing patched yet, MAPPY projects surface 1's numbered grid.
  2. Open MAP (or drag on the card) and pull the grid's four corners until it lines up with the physical screen / cube face.
  3. Hit + to add surface 2 (it drops in as an inset grid showing the digit “2”), map it onto the next face, and repeat — up to six surfaces.
  4. Connect a video source into inN — surface N's grid is replaced by that feed, warped into the quad you already mapped. Flip GRID back on any time to re-check alignment.
Generated from packages/web/src/lib/{audio,video}/module-registry.ts · repo