aboutsummaryrefslogtreecommitdiff
path: root/docs/reference/msh.md
blob: 25aaad2cf3721368bbbd03962f9aa4a5a810bc4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# MSH

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

## Entry map

```text
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:

```c
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`:

```c
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:

```c
#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.