Files
fparkan/docs/reference/msh.md
T
Valentin Popov 78fc5f1deb
Docs Deploy / Build and Deploy MkDocs (push) Successful in 34s
Test / Lint (push) Failing after 1m7s
Test / Test (push) Has been skipped
Test / Render parity (push) Has been skipped
docs: rewrite MkDocs documentation
2026-06-22 01:58:51 +04:00

1.9 KiB

MSH

Файл *.msh является NRes-контейнером. Geometry, узлы, slots, batches, animation и служебные streams лежат в entries с разными type_id.

Entry map

type 1   nodes and slot selection
type 2   header 0x8C + Slot68 records
type 3   positions float3
type 4   packed normals
type 5   packed UV0
type 6   index buffer u16
type 7   triangle descriptors
type 8   animation keys
type 9   service stream
type 10  strings and node names
type 13  Batch20 records
type 15  auxiliary stream
type 17  auxiliary data
type 18  rare stream
type 19  animation frame map
type 20  rare auxiliary table

Reader ищет entries по type, но сохраняет исходный порядок для roundtrip.

Node and slot selection

Type 1 обычно состоит из records по 38 bytes:

struct Node38 {
    uint16_t hdr0;
    uint16_t parent_or_link;
    uint16_t anim_map_start;
    uint16_t fallback_key;
    uint16_t slot_index[15];
};

slot_index[lod * 5 + group] выбирает geometry slot. 0xFFFF означает отсутствие геометрии для комбинации LOD/group.

Slot and batch

Type 2 содержит header 0x8C, затем Slot68:

struct Slot68 {
    uint16_t tri_start;
    uint16_t tri_count;
    uint16_t batch_start;
    uint16_t batch_count;
    float aabb_min[3];
    float aabb_max[3];
    float sphere_center[3];
    float sphere_radius;
    uint32_t opaque[5];
};

Type 13 задаёт draw ranges:

#pragma pack(push, 1)
struct Batch20 {
    uint16_t batch_flags;
    uint16_t material_index;
    uint16_t opaque4;
    uint16_t opaque6;
    uint16_t index_count;
    uint32_t index_start;
    uint16_t opaque14;
    uint32_t base_vertex;
};
#pragma pack(pop)

Index check выполняется как base_vertex + index < vertex_count для всего используемого slice.