Parse the moby per-class part table
A moby class span does not start with its geometry. The first u32 is the offset of a part table, and the table is 16-byte records of vertex offset, vertex count, an unestablished second count, the next part offset and flags. Parts tile: vertex_offset + 16 * vertex_count == next_part. The stride is never assumed anywhere -- it falls out of that identity, which is what pins the record size and the field boundaries. The identity holds for 43,467 of 43,467 part records across every moby class on all 27 levels, and the parser rejects any span that violates it rather than returning a plausible wrong answer. Two terminations are needed. A zero vertex_offset ends the run, but 172 records on the disc have a zero vertex_offset and a zero next_part while still carrying a vertex count. Stopping only on the first leaves 99.6% instead of 100% and quietly includes a second table as if it were parts. 1,270,802 vertices over 4,560 class spans; 116 spans carry no geometry. Vertices are 16 bytes of VIF-packed half-float quads cycling through four distinct words. Handed back raw -- unpacking them is separate work from finding them, and second_count is recorded but not guessed at.
This commit is contained in:
@@ -794,7 +794,32 @@ Class entries are 0x20 bytes in `core_index.bin`, fields
|
||||
`geom_offset, o_class, unknown_8, unknown_c, textures[16]`; all 238 level-0
|
||||
moby classes carry `textures == ffff..ff`, i.e. no texture slots.
|
||||
|
||||
`geom_offset` points into `core_data`, and the spans tile without overlap. The
|
||||
data at that offset does not start with a recognisable header -- it opens with
|
||||
zero words and then packed half-float VIF data (`55 55 15 3e` shows up 4 bytes
|
||||
in). Not decoded.
|
||||
`geom_offset` points into `core_data`, and the spans tile without overlap.
|
||||
|
||||
The span does not start with the geometry. Its first `u32` is the offset of a
|
||||
part table, and the table is 16-byte records:
|
||||
|
||||
```
|
||||
+0x00 u32 vertex_offset from the start of the class
|
||||
+0x04 u16 vertex_count
|
||||
+0x06 u16 second_count meaning not established
|
||||
+0x08 u32 next_part
|
||||
+0x0c u32 flags
|
||||
```
|
||||
|
||||
Parts tile: `vertex_offset + 16 * vertex_count == next_part`. The stride is not
|
||||
assumed -- it falls out of that identity, which is what pins the record size
|
||||
and the field boundaries. It holds for 43,467 of 43,467 part records across
|
||||
every moby class on all 27 levels.
|
||||
|
||||
Two terminations are needed, not one. A zero `vertex_offset` ends the run, but
|
||||
172 records across the disc have a zero `vertex_offset` *and* a zero
|
||||
`next_part` while still carrying a vertex count; stopping only on the second
|
||||
is what leaves 99.6% instead of 100%. A zero `next_part` means the record
|
||||
starts a different table rather than a part.
|
||||
|
||||
Totals: 1,270,802 vertices over 4,560 class spans, 116 of which carry no
|
||||
geometry.
|
||||
|
||||
Vertices are 16 bytes of VIF-packed half-float quads, cycling through four
|
||||
distinct 32-bit words. Not unpacked -- handed back raw.
|
||||
|
||||
+8
-1
@@ -205,7 +205,14 @@ Phase 1 hands over the extents; this phase works out what each one contains.
|
||||
- [ ] `tfrag` — terrain: LOD chains, strips, morph targets
|
||||
- [ ] `tie` — instanced environment geometry, fat vertices
|
||||
- [ ] `shrub` — foliage and decorative meshes
|
||||
- [ ] `moby` — dynamic actors; `moby_anim` — skeletal animation
|
||||
- [x] `moby` — per-class model geometry. A class span opens with a `u32`
|
||||
pointing at a part table of 16-byte records; parts tile exactly, with
|
||||
`vertex_offset + 16 * vertex_count == next_part` holding for **43,467 of
|
||||
43,467** parts across every class on all 27 levels. That identity is what
|
||||
makes the record size fall out of the data rather than being assumed.
|
||||
1,270,802 vertices over 4,560 class spans; 116 spans carry no geometry.
|
||||
Vertices are 16-byte VIF-packed half-float quads, handed back raw.
|
||||
- [ ] `moby_anim` — skeletal animation, still open
|
||||
- [x] `collision` — container framing. A 0x40-byte header self-describes: it
|
||||
carries its own size and the payload size, and `header + payload` stays
|
||||
inside `core_data` on all 27 levels. 41,481,520 payload bytes across 19
|
||||
|
||||
Reference in New Issue
Block a user