Commit Graph

1 Commits (c711ae2831aa730a03c9972569a841cac1b80078)

Author SHA1 Message Date
Amir Alexander Abdelbaki c711ae2831 Solve gem placement instead of dialling it in
Gem slots could not be positioned by hand because translation is not the
gem's position. The gem model is `item/generated`: a 2x2 sprite block at the
dead centre (8,8) of a 16x16 sheet, so its geometry sits 8px from the model
origin on every axis. MIAPI's Transform.toMatrix is T * Rx * Ry * Rz * S with
no centring offset, so rotation pivots on that origin and throws the gem up to
12px away. Translation is whatever cancels the throw.

    world = pivot + flip(T + R*S*c),  flip = negate x,y,  c = (8,8,8)

`flip` is the block-model(+y up) -> ModelPart(+y down) conversion. Inverting
it gives T from a desired anchor, so tools/solve_gems.py takes targets in
plain world pixels and asserts the result forward-evaluates back.

The helmet gem is the exception: it chains through the hat slot, which scales
by 1.25 and lifts by -3.925, and does NOT go through the flip. Solving it with
the flip inverts y and drops the gem past the chin to the floor. The chain is
recorded against two in-game sightings that pin it.

Also:

- Drop the stray no-origin model entry from all eight limb gem/case modules.
  Without an origin a model falls through the slot's z180 and lands mirrored
  in x and y - which is why a right-arm gem showed up above the left shoulder.
- Give the helmet and backtank gems origin-carrying modules. Their slots took
  `gem_armor_medium`, whose only members declare no origin, so the gem was
  drawn in the body pass and never appeared. Apothic cases included so
  repointing the slots loses nothing.
- Compensate the z180 in the helmet model UVs. Geometry in these models is
  already authored around the flip; UVs cannot be, so every face rendered
  rotated 180. The face that shows on top is the one authored `down`.
- Remove the misaligned placeholder bezels from the four limb sockets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 20:28:07 +02:00