cutan.compile.gaze¶
Ambient saccades for a cutout rig’s pupils: a seeded generator (an#99, epic #9 Wave 6).
Pure Python, no renderer. Given an entity’s name, a shot’s duration and its
frame rate, produce a step track of pupil offsets — where the eyes rest,
and when they jump — that the face solver adds onto the pupil nodes’ x /
y beside any authored gaze. Steps, not tweens: at 24 fps a frame is
41.7 ms and a small saccade is 20–200 ms, so a jump between two frames is the
honest rendering (the way the compiled blink squash samples at frame times).
The statistics are design values, labelled so: the canonical source
(“Eyes Alive”, Lee, Badler & Badler, SIGGRAPH 2002) was unreachable when this
was designed, and nothing was transcribed from memory. Fixation lengths are
right-skewed with a ~200 ms peak and a long tail, so they are drawn from a
gamma clipped to [FIXATION_MIN_S, FIXATION_MAX_S]; amplitudes are mostly
small with a rare large jump and a horizontal bias; and a jump above
BLINK_COUPLED_AMPLITUDE is moved to the centre of the nearest blink window
within BLINK_COUPLING_WINDOW_S when one exists, because gaze-evoked blinks
hide the pop.
Seeding follows the blink pattern — a pure function of the entity name — so
renaming a character re-seeds its saccades (the recorded blink hazard); the
seed is stamped into the compiled scene’s meta beside blink_phases.
Integer seeding of random.Random is version-stable.
>>> track = saccade_track("gale", duration=2.0, fps=24)
>>> track[0].time, all(t.time <= 2.0 for t in track)
(0.0, True)
>>> track == saccade_track("gale", duration=2.0, fps=24) # deterministic
True
>>> track != saccade_track("nora", duration=2.0, fps=24) # per entity
True
Module Attributes
XOR'd into the entity-name hash so saccades and blinks never share a seed. |
Functions
|
The generator's seed for an entity — a pure function of its name. |
|
Step keyframes on frame times, seeded by |
Classes
|
The pupils rest at |
- cutan.compile.gaze.GAZE_SALT: int = 27182¶
XOR’d into the entity-name hash so saccades and blinks never share a seed.
- class cutan.compile.gaze.GazeStep(time, x, y)[source]¶
Bases:
objectThe pupils rest at
(x, y)(axis units) fromtimeon.
- cutan.compile.gaze.gaze_seed(entity_id)[source]¶
The generator’s seed for an entity — a pure function of its name.
>>> gaze_seed("gale") == gaze_seed("gale") and gaze_seed("gale") != gaze_seed("nora") True- Return type:
- cutan.compile.gaze.saccade_track(entity_id, *, duration, fps, blink_windows=None, amplitude=1.0)[source]¶
Step keyframes on frame times, seeded by
entity_id.amplitudescales every jump (0 = the eyes hold centre; the design values assume 1).blink_windowsare the entity’s compiled blink windows, for the coupling rule.