From e27c40e7384a827aa3a8373e9258d7c5c38659bc Mon Sep 17 00:00:00 2001 From: ReaperOfVeriod Date: Tue, 13 Oct 2026 05:19:06 +0200 Subject: [PATCH] Explain the tie texcoord residual: i16[3] selects the encoding The texcoords are 12-bit fixed on 82.5% of vertices, not 100%, and the residual had no explanation. Grouped by the vertex's i16[3] slot across 95,612 vertices on levels 0-2, the buckets separate completely: i16[3] n % / 4096 % / 256 negative 333 1.2% 1.2% == 0 5,851 29.2% 60.7% 1..63 28,884 92.7% 94.3% 64..255 54,606 92.3% 93.8% 256..511 8 0.0% 0.0% 512..1023 5,391 0.0% 0.0% >= 1024 539 0.2% 0.2% The residual is fully accounted for. 87.3% of vertices sit in 1..255 at about 92.5% fixedness, contributing 0.873 * 0.925 = 80.8 points; the 5,851 at i16[3] == 0 contribute 1.8 more. That is the 82.5% measured, to the point. The remaining ~6% are not 12-bit fixed at all. i16[3] >= 256, and negatives, score 0% at BOTH 4096 and 256 -- 6,271 vertices in an encoding this reading does not see. And i16[3] == 0 scores 29.2% at 4096 but 60.7% at 256, which is a third distribution rather than a weaker version of the same one. What this establishes: i16[3] is a per-vertex packed attribute whose value SELECTS HOW the texcoord pair is stored, rather than an independent field sitting beside the texcoords. 1-255 is the ordinary case, 0 is special, 256-and-up and negatives are a different encoding. What those three cases MEAN is still open -- texture index, normal index, flag or a combination -- but it is now a field whose role is known, which is more than "packed word". Worth noting the shape of the claim this replaces: "the texcoords are 12-bit fixed at i16[4]/i16[5], 73.6% of the time, unexplained". The field position was right; the 73.6% was a population average over three encodings. Partitioning by the one variable that separates them turns a mystery into a lookup -- rule 3a again, and the third time this session that partitioning a mystery produced the answer rather than merely bounding it. --- docs/formats/core-data-regions.md | 41 +++++++++++++++++++++++++++++++ docs/roadmap.md | 16 +++++++----- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/docs/formats/core-data-regions.md b/docs/formats/core-data-regions.md index 25ada38..0a5810d 100644 --- a/docs/formats/core-data-regions.md +++ b/docs/formats/core-data-regions.md @@ -1718,3 +1718,44 @@ space for collision is now genuinely exhausted -- the bytes are available, they are verbatim, the grid is known, and three independent segmentation theories have failed on the whole population. Further probing without the loader's own logic is not going to converge. + +## Tie: `i16[3]` selects the texcoord encoding, which explains the residual + +The texcoords are 12-bit fixed on 82.5% of vertices, not 100%. Grouped by the +vertex's `i16[3]` slot across **95,612 vertices on levels 0-2**, the buckets +separate completely: + + i16[3] n % / 4096 % / 256 + negative 333 1.2% 1.2% + == 0 5,851 29.2% 60.7% + 1..63 28,884 92.7% 94.3% + 64..255 54,606 92.3% 93.8% + 256..511 8 0.0% 0.0% + 512..1023 5,391 0.0% 0.0% + >= 1024 539 0.2% 0.2% + +**The residual is fully accounted for.** 87.3% of vertices sit in `1..255` at +about 92.5% fixedness, which contributes 0.873 x 0.925 = 80.8 points; the 5,851 +at `i16[3] == 0` contribute 1.8 more. That is the 82.5% measured, to the point. + +The remaining ~6% are **not 12-bit fixed at all**: + +- `i16[3] >= 256`, and negatives, score **0%** at both 4,096 and 256 -- 6,271 + vertices using an encoding this reading does not see; +- `i16[3] == 0` scores 29.2% at 4,096 but **60.7% at 256**, which is a third + distribution rather than a weaker version of the same one. + +**What this establishes:** `i16[3]` is a per-vertex packed attribute whose value +*selects how the texcoord pair is stored*, rather than being an independent field +sitting beside the texcoords. Values 1-255 are the ordinary case; 0 is special; +256 and above, and negatives, are a different encoding entirely. + +**Not established:** what any of those three cases means. Whether `i16[3]` is a +texture index, a normal index, a flag or a combination is still open -- but it is +now a field whose *role* is known, which is more than "packed word". + +Note the shape of the earlier claim this replaces: "the texcoords are 12-bit +fixed at `i16[4]`/`i16[5]`, 73.6% of the time, unexplained". The field position +was right; the 73.6% was a population average over three encodings, which is +exactly the pooled-number problem rule 3a describes -- partitioning by the one +variable that separates them turns a mystery into a lookup. diff --git a/docs/roadmap.md b/docs/roadmap.md index 78f7f9c..0e63719 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -293,13 +293,17 @@ Phase 1 hands over the extents; this phase works out what each one contains. against 1.1% for `(0,1)` and 4.8% for `(2,3)`. The `(6,7)` pair scores *higher* at 76.6% and is **not** a texcoord -- it is the near-constant `4096, 0` pair, which is trivially two multiples of 4,096. +- [x] `i16[3]` **selects the texcoord encoding**, which explains the residual. + Grouped across 95,612 vertices on levels 0-2: `1..63` and `64..255` score + 92.7% and 92.3% 12-bit fixed, `== 0` scores 29.2% at 4,096 but **60.7% at + 256** -- a third distribution -- and everything at 256 or above, or + negative, scores **0%** at both. The 87.3% of vertices in `1..255` + contribute exactly the 82.5% measured overall, so the residual is fully + accounted for. It is a field whose *role* is known even though its meaning + is not. - [ ] The remaining tie vertex **fields are not named.** `i16[0..3]` span the full - `i16` range with 10,803-13,421 distinct values each, so they are neither - texcoords nor small fields; they are most likely position plus a packed - word, but that is not established. The texcoord rate is 73.6% rather than - 100% and the vertex base is confirmed to be `vert_ofs` alone (adding the - shader or control region makes it worse), so the residual is not a - mislocated base. + `i16` range with 10,803-13,421 distinct values each. `i16[0..2]` are most + likely position, but that is not established. - [~] `shrub` — class table done (48-byte entries, not 32; reading shrub at 32 still gives 231 sane-looking entries of 358, which is the hazard). Geometry header parsed and checked field by field on all 358 spans: