Skip to content

Camera bucket catalogue

The 16 canonical camera buckets defined by CameraBuckets in package:pose_flow. Bucket IDs are the stable strings that appear in .pose files’ angleBands and in AngleBand.cameraBucket.

The 3 × 5 + 1 ring

A semi-sphere orbit around the user:

90° L45° LFront45° R90° R
Head (overhead, CameraHeight.overhead)90left_overhead45left_overheadfront_overhead45right_overhead90right_overhead
Hip (CameraHeight.hip)90left_hip45left_hipfront_hip45right_hip90right_hip
Feet (floor, CameraHeight.floor)90left_floor45left_floorfront_floor45right_floor90right_floor

Plus the 16th specialised bucket: behind_hip for movements that need a back view.

Naming convention

{azimuth}_{height}
  • azimuth, one of front, 45left, 45right, 90left, 90right, behind.
  • height, one of overhead, hip, floor.

The ID convention uses overhead + floor for backward-compat with existing .pose files. User-facing labels use Head + Feet (via CameraBucket.displayLabel).

Azimuth semantics

  • = camera in front of the subject (front_* buckets).
  • +45° = camera to the subject’s right (45right_*).
  • +90° = camera fully on the subject’s right side (90right_*).
  • -45° = camera to the subject’s left (45left_*).
  • -90° = camera fully on the subject’s left side (90left_*).
  • ±180° = camera behind the subject (behind_hip).

When the subject rotates clockwise (from above), the camera appears to move counter-clockwise relative to them, same azimuth semantics.

Height semantics

TierLens positionTypical rig
floor (“Feet”)Camera on the ground, looking upPhone on the floor for hip-hinge / knee-drive authoring
hipCamera at hip levelPhone on a chair / low table, the default
overhead (“Head”)Camera at face / eye levelLaptop on a desk, tripod at eye height, the most common live-camera rig

overhead is named for historical reasons; in user-facing copy we say Head. Same bucket either way.

CameraBucket Dart API

class CameraBucket {
final String id; // e.g. 'front_hip'
final double azimuthDeg; // e.g. 0
final CameraHeight height; // e.g. CameraHeight.hip
}
abstract final class CameraBuckets {
static const CameraBucket frontHip;
static const CameraBucket fortyFiveLeftHip;
static const CameraBucket fortyFiveRightHip;
static const CameraBucket ninetyLeftHip;
static const CameraBucket ninetyRightHip;
static const CameraBucket behindHip;
// ... overhead + floor variants
static const List<CameraBucket> all; // length 16
static CameraBucket? byId(String id);
static double azimuthDistance(double a, double b);
}
  • byId(String id) returns the bucket for a given persisted id, or null when the id isn’t part of the canonical set.
  • azimuthDistance(a, b) returns the smallest signed angular distance between two azimuths on the ±180° ring, in [0, 180]. Used by the runtime to find nearest authored neighbours when interpolating per-bucket bands.

displayLabel

CameraBucket.displayLabel formats a user-friendly string:

front_hip → "Front · Hip"
45left_overhead → "45° Left · Head"
90right_floor → "90° Right · Feet"
behind_hip → "Behind · Hip"

Use this in any user-facing chrome. Reserve the raw id for machine-readable contexts (logs, persisted state, JSON keys).

Authoring ordering

CameraBuckets.all is sorted so frontHip is first. The runtime treats “first authored bucket in canonical order” as the primary, which is the fallback used when bucket detection confidence is low. So if a movement authors only front_hip + 90left_hip, the runtime falls back to front_hip on low confidence.