Skip to content

motion: hold a bowl in both hands or a cup in one, sat, and eat and drink from them (#825, its 3) - #839

Merged
nicolas-maman merged 6 commits into
mainfrom
feat/motion-eat
Oct 20, 2026
Merged

nicolas-maman merged 6 commits into
mainfrom
feat/motion-eat

Conversation

@nicolas-maman

@nicolas-maman nicolas-maman commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

The next slice of #825 (what a game's day asks of a figure), its 3 whole: sit and eat from a bowl held in both hands, and drink from a cup.

What a sitter holds is an interaction point of its own, as a GTA V scenario's prop and an Unreal Smart Object's hand slots are: the places on it the hands grip, in its own frame.

  • motion.hold(body, item, left, right) takes item, sat. Each grip goes to the hand on the side nearer it. It rests over the thighs, LAP_AHEAD ahead of the hips' middle.
  • Each step the item is placed, and the hands are solved onto its grips with the arms' two-bone solve, elbows down and out: the same solve that puts the hands on the thighs.
  • The hands go from the thighs to the grips over TAKE (0.5 s), eased, and back on motion.let_go(body). Set onto the grips at once, the arms turned 22.7 degrees in a step, which the test's pop check catches.
  • motion.eat(body) takes a bite: the item comes up in front of the mouth over BITE_RAISE (0.8 s), stays BITE_STAY (0.6 s), and goes back down over BITE_LOWER (0.8 s), eased. eating and holding say where it is.
  • motion.mouth(body) is the figure's own: part way up its neck's body, ahead by that body's thickness. Any rig's head serves, with nothing set per clip.
  • Standing up puts the item down first (put_down).
  • motion.hold_cup(body, cup, grip, right) takes a cup in one hand. It rests over that side's thigh, and the other hand stays on its own thigh.
  • motion.drink(body) takes a sip: the cup's rim comes to the lips, CUP_AHEAD (4 cm) ahead of the mouth and CUP_UNDER (2 cm) under it, tipped toward the face by CUP_TILT (60 degrees) at the top, as a cup is tipped to drink from it.

Measured (tests/test_eat.ae: the box man, POWERED, sat on a 0.4 m log, three bites, let go, stands up):

measured held to
each palm off its grip, bites and all 0.05 cm 3 cm (#825)
the bowl from the mouth at a bite's top 11 cm 13 cm (it is held 10 cm ahead of the mouth, 5 under)
the mouth from the drawn head 10 cm 15 cm
the toes sliding along the ground 3.8 mm 5 mm
the worst turn of any body in a step 5.0 degrees 6 degrees
a cup, two sips: the right palm off its grip 0.03 cm 3 cm
a cup: the left hand off its thigh's middle, level-wise 2.0 cm 12 cm
a cup: its rim from the mouth, and its tip toward the face, at a sip's top 0.6 cm, 60 degrees 6 cm, 40 degrees or more
a cup: the toes sliding, and the worst turn in a step 3.8 mm, 4.6 degrees 5 mm, 6 degrees

The palm is where a grip is held: the forearm's line on past the drawn wrist, as far as the forearm's body reaches past it (4.5 cm on the box man, which has no fingers). Measured at the wrist, the same hands read 4.5 cm off. Let go, the hands are back on the thighs (2 cm from the thigh's middle), and it stands up POWERED and upright.

docs/motion.md: holding and eating. The sitting section is brought up to #833 (set down against the seat's surface) and #834 (the hands where the arms reach), and its table to the round log.

Next: item 5 (kneel by someone lying on the ground and work over them with both hands).

Tested locally: on Aether 0.834.0 and aephysics f0bd6d6, the motion gate (34 suites) plus test_go_to, test_sit, test_eat, test_lie, test_locomotion, test_characters_meet, test_physics, test_ik and test_gmath all pass, 43 of 43, on the bowl commit. On the cup commit, test_eat (15 checks), test_sit, test_lie and test_get_up pass. The plaza scorecard is not run: no one sits in the plaza.

Dependencies: unchanged, held. CI stays on Aether 0.834.0, aephysics f0bd6d6 and aether-ui dcc1bd48, as on main.

  • This PR moved to Aether 0.836.0, aephysics 32aa169 and aether-ui c55a375a, with every program compiling on 0.836's ownership rules.
  • The Windows leg then failed in gcc. The net module's optional maker slots must be typed fn(@keep ptr, int), because the makers keep their context, and that makes them closures. Their if maker == null tests generate C that compares a closure struct with a pointer. That is Aether's, reported to its session with a repro.
  • The editor also has two @keep functions in C function pointer slots still to move.
  • The migration waits on branch feat/aether-0836, for its own PR. Only channel's dead return stays here.

Part of #825 and #790.

What a sitter holds is an interaction point of its own, as a GTA V
scenario's prop and an Unreal Smart Object's hand slots are: the places
on it the hands grip, in its own frame.

- hold(body, item, left, right) takes it, sat; each grip goes to the
  hand on the side nearer it. It rests over the thighs, LAP_AHEAD ahead
  of the hips' middle. Each step it is placed and the hands are solved
  onto its grips (the arms' two-bone solve), elbows down and out.
- The hands go to the grips over TAKE (0.5 s) and back on let_go, eased:
  set onto the grips at once, the arms turned 22.7 degrees in a step.
- eat(body) takes a bite: up in front of the mouth over BITE_RAISE,
  BITE_STAY there, down over BITE_LOWER.
- mouth(body) is the figure's own, up its neck's body, so any rig's head
  serves with nothing set per clip. Standing up puts the item down first.

tests/test_eat.ae: sat on a 0.4 m log, three bites. Each palm (the
forearm's line on past the wrist, as far as its body reaches) is 0.05 cm
off its grip at the most (held to #825's 3 cm). The bowl comes to 11 cm
of the mouth (13), the toes slide 3.8 mm (5) and no body turns more than
5.0 degrees in a step (6). docs/motion.md: holding and eating, and the
sitting section brought up to #833 and #834.
hold_cup(body, cup, grip, right) takes a cup in one hand: it rests over
that side's thigh, and the other hand stays on its own. drink(body) takes
a sip: the rim comes to the lips, CUP_AHEAD ahead of the mouth and
CUP_UNDER under it, and the cup is tipped toward the face by CUP_TILT (60
degrees) at the top, eased as it comes up and goes down.

tests/test_eat.ae: sat again with a cup in its right hand, two sips. The
right palm is 0.03 cm off the grip at the most and the left hand stays 2
cm from its thigh's middle. At each sip's top the rim is 0.6 cm from the
mouth, tipped 60 degrees. The toes slide 3.8 mm and no body turns more
than 4.6 degrees in a step.
@nicolas-maman nicolas-maman changed the title motion: hold something in both hands sat, and eat from it (#825, its 3) motion: hold a bowl in both hands or a cup in one, sat, and eat and drink from them (#825, its 3) Oct 20, 2026
Aether 0.836.0 fixes aether#3023: @target("avx2") regions no longer an
internal compiler error at -O0 on Win64 GCC. ae3d held at 0.834.0 for
it, because aephysics b37fae2 and later put AVX2 copies into every x86
build and ae3d's suites build at -O0. It also has aether#3026 (no false
W1002 after an early return on a module var) and the rest of its batch.

aephysics 48065aa (#183 and #185): every open aephysics issue closed,
wide SAT, run-time SIMD width, std.math's sqrt so -O0 Windows builds give
the optimized build's bits.

aether-ui c55a375a: 0.835's one name per operation (E0305), and the GTK4
script-rule buffer holds its longest rule (aether-ui#220), so the editor
builds without -Wformat-truncation.
…ams (E0902); channel's dead return

Aether 0.836.0 fixes aether#3023 (the -O0 Win64 GCC crash that held ae3d
on 0.834.0), but its two new E0902 rules fail 135 of ae3d's 252 programs:
- a borrowed ptr parameter returned (an interior pointer handed back from
  the allocation a function is given): aephysics 48065aa at 13 sites, and
  ae3d's blob.slice and vkdesc.cluster_at;
- a @keep function stored as a C function pointer: the renderer backends'
  set_skybox and set_overlay in their fn tables.
0.835.0 compiled them all. The repros went to the Aether session and the
aephysics session; the ci.yml hold names the break. aether-ui back to
dcc1bd48 with it.

channel's line pump ended with a `return true` after a `while true`
that only leaves by returning: unreachable, as 0.836.0's W1002 finds.
…s ownership rules

Aether 0.836.0 fixes aether#3023 (@target("avx2") regions an internal
compiler error at -O0 on Win64 GCC), which held ae3d on 0.834.0. Its
E0902 rules and std's last long names asked for these changes, and with
them all 255 programs ci.sh builds compile without an error or a warning:

- A pointer returned from a borrowed parameter is declared @into
  (aether#2990): blob.slice and vkdesc.cluster_at hand back a pointer into
  the bytes they are given. aephysics 32aa169 does the same at 13 sites.
- A fn slot whose function keeps its argument says so (aether#2980), and
  the function goes in uncast: a cast makes a C function pointer, whose
  parameters borrow. The backends' set_skybox and set_overlay take their
  state as a ptr and keep what they are given, through core.Backend's and
  the engine's slots and the setters that call them. The net module's
  maker slots may keep the context they are handed.
- os.aether_args_count and os.aether_args_get are os.args_count and
  os.args_get (0.836 exports one name each).
- probe's read_line ended with an unreachable `return 0 - 1` after a
  `while true` that only leaves by returning (W1002).

aether-ui c55a375a: 0.835's one name per operation (E0305), and the GTK4
script-rule buffer holds its longest rule (aether-ui#220).
… compared with null is invalid C

Moved to Aether 0.836.0 and aephysics 32aa169, with every program
compiling on 0.836's ownership rules, the Windows leg failed in gcc: the
net module's optional maker slots must be typed fn(@keep ptr, int) (the
makers keep their context), which makes them closures, and its
`if maker == null` comparisons generate C that compares a closure struct
with a pointer. That is Aether's (reported to its session with a
repro). The editor also has two @keep functions in C function pointer
slots still to move. The migration waits on branch feat/aether-0836;
this PR, the eating and drinking, goes back to main's pins.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant