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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use crate::{index_range, ReadableRelative, Vector};
use bytemuck::{Pod, Zeroable};
use std::mem::size_of;

#[derive(Debug, Clone, Copy, Zeroable, Pod)]
#[repr(C)]
pub struct VvdHeader {
    pub id: i32,
    pub version: i32,
    pub checksum: [u8; 4],
    pub lod_count: i32,
    lod_vertex_count: [i32; 8],
    fixup_count: i32,
    fixup_index: i32,
    vertex_index: i32,
    tangent_index: i32,
}

impl VvdHeader {
    pub fn fixup_indexes(&self) -> impl Iterator<Item = usize> {
        index_range(
            self.fixup_index,
            self.fixup_count,
            size_of::<VertexFileFixup>(),
        )
    }

    pub fn has_fixups(&self) -> bool {
        self.fixup_count > 0
    }

    pub fn vertex_indexes(&self, lod: i32) -> Option<impl Iterator<Item = usize>> {
        if lod < self.lod_count {
            Some(index_range(
                self.vertex_index,
                self.lod_vertex_count[lod as usize],
                size_of::<Vertex>(),
            ))
        } else {
            None
        }
    }

    pub fn tangent_indexes(&self, lod: i32) -> Option<impl Iterator<Item = usize>> {
        if lod < self.lod_count {
            Some(index_range(
                self.tangent_index,
                self.lod_vertex_count[lod as usize],
                size_of::<[f32; 4]>(),
            ))
        } else {
            None
        }
    }
}

#[derive(Debug, Clone, Zeroable, Pod, Copy)]
#[repr(C)]
pub struct VertexFileFixup {
    pub lod: i32,
    pub source_vertex_id: i32,
    pub vertex_count: i32,
}

impl ReadableRelative for VertexFileFixup {}

#[derive(Debug, Clone, Zeroable, Pod, Copy)]
#[repr(C)]
pub struct Vertex {
    pub bone_weights: BoneWeight,
    pub position: Vector,
    pub normal: Vector,
    pub texture_coordinates: [f32; 2],
}

impl ReadableRelative for Vertex {}

static_assertions::const_assert_eq!(size_of::<Vertex>(), 48);

#[derive(Debug, Clone, Zeroable, Pod, Copy)]
#[repr(C)]
pub struct BoneWeight {
    pub weight: [f32; 3],
    pub bone: [u8; 3],
    pub bone_count: u8,
}

static_assertions::const_assert_eq!(size_of::<BoneWeight>(), 16);

#[derive(Debug, Clone, Zeroable, Pod, Copy)]
#[repr(C)]
pub struct Tangent {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub w: f32,
}