portrait: measure SetPosition's unit instead of fitting it
One `WOW_BOOTH_LOG` run with Tmog open printed every term, so the factor is arithmetic now rather
than a fit:
- The cards draw through the paper-doll camera, logged `eye=(0.003, 1.103, -2.919)`, and the same
run logged the dwarf's `head_y=1.364`.
- Tmog's browse cards frame on the slot being browsed, so its per-race **head** row is a request
to put that race's head on the camera's axis. The dwarf row's vertical is `-1.2`.
- Centring the head needs `1.364 - 1.103 = 0.261` model units against a request of `1.2`:
**0.2175**, rounded to 0.22.
The same run confirmed the whole chain end to end: the logged pose inverted back to
`(3.72, 0, 0.489)` at facing 3.2, and `Tmog.lua:332` reads `{ 3.8, 0, 0.5, 3.2 }` — the small gap
is the previous factor, `G48` at grom's actual aspect.
It cross-checks on depth: the head row's `6.3` then moves the model 1.37 of its 2.92 standoff,
leaving it 1.55 out — a view about 0.75 units tall around a head of roughly 0.35. The two earlier
values are what make the arithmetic worth trusting: 1.0 put every card *behind* its camera and the
grid drew empty; `G48` ≈ 0.49 left them 1.06 out, the extreme close-up in the screenshot.
Still a measurement of an addon's table against this client rather than of the reference's own
root, and the constant says so.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
@@ -761,10 +761,33 @@ pub(crate) fn pane_bake_size(longest_px: u32) -> u32 {
|
||||
#[derive(Resource, Default)]
|
||||
pub(crate) struct PaneBakeSizes(pub(crate) HashMap<String, u32>);
|
||||
|
||||
/// Each drawn pane's `Model:SetPosition`, as the translation its booth's model root carries: one
|
||||
/// model unit per `SetPosition` unit, in bevy's axes, converted at the publish so no booth has to
|
||||
/// know the widget's coordinate order. The extract's `ModelPane` arm says why the reference's
|
||||
/// `· layoutScale` is deliberately left off here.
|
||||
/// Model units per `SetPosition` unit on the booth path, **measured** rather than traced.
|
||||
///
|
||||
/// The measurement, off one `WOW_BOOTH_LOG` run with Tmog open, because every term in it is a
|
||||
/// number this client printed:
|
||||
///
|
||||
/// - Tmog's browse cards frame on the slot being browsed, so its per-race head row is a request
|
||||
/// to put that race's head on the pane camera's axis. For a dwarf that row's vertical is
|
||||
/// `-1.2` (`Tmog.lua:248`).
|
||||
/// - The cards draw through the paper-doll camera, logged as `eye=(0.003, 1.103, -2.919)`, and
|
||||
/// the same run logged the subject's `head_y=1.364`.
|
||||
/// - So the displacement that centres the head is `1.364 - 1.103 = 0.261` model units, against a
|
||||
/// request of `1.2`: **0.2175**, rounded here.
|
||||
///
|
||||
/// It cross-checks on depth. At this factor the head row's `6.3` moves the model 1.37 of its
|
||||
/// 2.92 standoff, leaving it 1.55 out — a view about 0.75 units tall around a head of roughly
|
||||
/// 0.35, which is a head filling half a card. The two previous values are what make the
|
||||
/// arithmetic worth trusting over a guess: 1.0 put every card *behind* its camera (the grid drew
|
||||
/// empty) and `G48` ≈ 0.49 left them at 1.06, the extreme close-up grom photographed.
|
||||
///
|
||||
/// Still a measurement of an addon's table against this client, not of the reference's own root;
|
||||
/// a capture of `0x76d1a0` would supersede it. The extract's `ModelPane` arm says why the
|
||||
/// reference's `· layoutScale` is left off entirely.
|
||||
pub(crate) const SET_POSITION_UNIT: f32 = 0.22;
|
||||
|
||||
/// Each drawn pane's `Model:SetPosition`, as the translation its booth's model root carries:
|
||||
/// [`SET_POSITION_UNIT`] model units per unit, in bevy's axes, converted at the publish so no
|
||||
/// booth has to know the widget's coordinate order.
|
||||
///
|
||||
/// A channel of its own, keyed by slot, for the reason [`PaneBakeSizes`] gives and one more: it
|
||||
/// serves the four stock window panes as well as the pool, and only the extract can see a pane's
|
||||
|
||||
@@ -1249,35 +1249,18 @@ fn convert_entry(
|
||||
// frozen (`0x7acf10`) rather than republished through the root, so the pane zooms and
|
||||
// pans — Tmog's wheel and right-drag.
|
||||
//
|
||||
// **`G48` model units per `SetPosition` unit**, `G48 = 1/√(a²+1)` for the screen
|
||||
// aspect — the client's own `[0x832a48]`, the same constant `Model::layout_unit`
|
||||
// inverts for the orthographic leg. Deliberately not the reference's `pos ·
|
||||
// layoutScale`: that factor belongs to the group the reference's root scales with it
|
||||
// (`T(pos·layout) · R(facing) · S(G48·(5/3)·modelScale·layout)`) and this booth's
|
||||
// root carries only the renormalizer, so spending the translate's share alone would
|
||||
// move a `scale="4"` pane's model four times its own size.
|
||||
//
|
||||
// The constant is **fitted, not traced**, and the fit is Tmog's own shipped table:
|
||||
// `Positions[slot][race][sex]` frames a browse card on the slot being browsed, so
|
||||
// each row is a displacement that must land the model's head in frame against that
|
||||
// race's authored camera. Across gnome (3.8, standoff ≈2.2), dwarf (6.3), human (8.8,
|
||||
// standoff 4.02) and night elf (11.8, the tallest) the ratio sits at 0.45–0.55, and
|
||||
// `G48` is 0.50 at a 16:9-ish panel. Shipping 1.0 put every card's model behind its
|
||||
// own camera and the grid drew empty, which is what pinned the order of magnitude.
|
||||
// A capture of the reference's root would settle it properly; until then this is a
|
||||
// measurement of an addon, not of the client.
|
||||
let diag = if h > 0.0 {
|
||||
((w / h) * (w / h) + 1.0).sqrt()
|
||||
} else {
|
||||
5.0 / 3.0
|
||||
};
|
||||
let g48 = 1.0 / diag;
|
||||
// **[`SET_POSITION_UNIT`] model units per `SetPosition` unit.** Deliberately not
|
||||
// the reference's `pos · layoutScale`: that factor belongs to the group the
|
||||
// reference's root scales with it (`T(pos·layout) · R(facing) ·
|
||||
// S(G48·(5/3)·modelScale·layout)`) and this booth's root carries only the
|
||||
// renormalizer, so spending the translate's share alone would move a `scale="4"`
|
||||
// pane's model four times its own size.
|
||||
booths.positions.0.insert(
|
||||
slot.to_string(),
|
||||
benilla_assets::coords::wow_to_bevy([
|
||||
position.0 * g48,
|
||||
position.1 * g48,
|
||||
position.2 * g48,
|
||||
position.0 * crate::portrait::SET_POSITION_UNIT,
|
||||
position.1 * crate::portrait::SET_POSITION_UNIT,
|
||||
position.2 * crate::portrait::SET_POSITION_UNIT,
|
||||
]),
|
||||
);
|
||||
// The aspect is published before the readiness check: the bake waits on the publish.
|
||||
@@ -2310,21 +2293,21 @@ mod extract_gate_tests {
|
||||
"{what}: got {got:?}, want {want:?}"
|
||||
);
|
||||
};
|
||||
// The window is 1024x768 in this harness, so `G48 = 1/√((4/3)²+1) = 0.6`.
|
||||
// `SET_POSITION_UNIT` is 0.22: `(2, 0.5, -0.25)` lands as `(-0.11, -0.055, -0.44)`.
|
||||
near(
|
||||
at(&app, UNIT_PANE_SLOTS[0]),
|
||||
Vec3::new(-0.3, -0.15, -1.2),
|
||||
Vec3::new(-0.11, -0.055, -0.44),
|
||||
"an addon's own pane publishes under the pooled slot it claimed",
|
||||
);
|
||||
// A stock name takes its window's booth, and its pane's position with it: the channel is
|
||||
// keyed by slot precisely so the four window panes are not a second path.
|
||||
near(
|
||||
at(&app, "paperdoll"),
|
||||
Vec3::new(0.0, 0.0, -0.6),
|
||||
Vec3::new(0.0, 0.0, -0.22),
|
||||
"a named pane publishes under its window's booth",
|
||||
);
|
||||
// `G48` model units per `SetPosition` unit: the pane's own layout scale does **not**
|
||||
// multiply it, because this booth's root does not scale by it either
|
||||
// A fixed number of model units per `SetPosition` unit: the pane's own layout scale does
|
||||
// **not** multiply it, because this booth's root does not scale by it either
|
||||
// (`framing::pane_root_scale_at`). Taking the translate's share of the reference's
|
||||
// `T(pos·layout) · R · S(…·layout)` group while dropping the scale's would move a
|
||||
// `scale="4"` Tmog card's model four times its own size.
|
||||
@@ -2335,7 +2318,7 @@ mod extract_gate_tests {
|
||||
app.update();
|
||||
near(
|
||||
at(&app, UNIT_PANE_SLOTS[0]),
|
||||
Vec3::new(-0.3, -0.15, -1.2),
|
||||
Vec3::new(-0.11, -0.055, -0.44),
|
||||
"a scaled pane moves its model by the same model units",
|
||||
);
|
||||
// A pane that stops drawing publishes nothing at all, so the booth keeps where it was
|
||||
|
||||
Reference in New Issue
Block a user