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° L | 45° L | Front | 45° R | 90° R | |
|---|---|---|---|---|---|
Head (overhead, CameraHeight.overhead) | 90left_overhead | 45left_overhead | front_overhead | 45right_overhead | 90right_overhead |
Hip (CameraHeight.hip) | 90left_hip | 45left_hip | front_hip | 45right_hip | 90right_hip |
Feet (floor, CameraHeight.floor) | 90left_floor | 45left_floor | front_floor | 45right_floor | 90right_floor |
Plus the 16th specialised bucket: behind_hip for movements that
need a back view.
Naming convention
{azimuth}_{height}azimuth, one offront,45left,45right,90left,90right,behind.height, one ofoverhead,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
0°= 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
| Tier | Lens position | Typical rig |
|---|---|---|
floor (“Feet”) | Camera on the ground, looking up | Phone on the floor for hip-hinge / knee-drive authoring |
hip | Camera at hip level | Phone on a chair / low table, the default |
overhead (“Head”) | Camera at face / eye level | Laptop 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.