1mod raw;
2
3use crate::{read_relative, ModelError, ReadRelative, Readable};
4use itertools::Either;
5use raw::*;
6pub use raw::{MeshFlags, StripFlags, StripGroupFlags, Vertex};
7use std::ops::Range;
8
9pub const MDL_VERSION: i32 = 7;
10
11type Result<T> = std::result::Result<T, ModelError>;
12
13#[derive(Debug, Clone)]
15pub struct Vtx {
16 pub header: VtxHeader,
17 pub body_parts: Vec<BodyPart>,
18}
19
20impl Vtx {
21 pub fn read(data: &[u8]) -> Result<Self> {
22 let header = <VtxHeader as Readable>::read(data)?;
23 Ok(Vtx {
24 body_parts: read_relative(data, header.body_indexes())?,
25 header,
26 })
27 }
28}
29
30#[derive(Debug, Clone)]
31pub struct BodyPart {
32 pub models: Vec<Model>,
33}
34
35impl ReadRelative for BodyPart {
36 type Header = BodyPartHeader;
37
38 fn read(data: &[u8], header: Self::Header) -> Result<Self> {
39 Ok(BodyPart {
40 models: read_relative(data, header.model_indexes())?,
41 })
42 }
43}
44
45#[derive(Debug, Clone)]
46pub struct Model {
47 pub lods: Vec<ModelLod>,
48}
49
50impl ReadRelative for Model {
51 type Header = ModelHeader;
52
53 fn read(data: &[u8], header: Self::Header) -> Result<Self> {
54 Ok(Model {
55 lods: read_relative(data, header.lod_indexes())?,
56 })
57 }
58}
59
60#[derive(Debug, Clone)]
61pub struct ModelLod {
62 pub meshes: Vec<Mesh>,
63 pub switch_point: f32,
64}
65
66impl ReadRelative for ModelLod {
67 type Header = ModelLodHeader;
68
69 fn read(data: &[u8], header: Self::Header) -> Result<Self> {
70 Ok(ModelLod {
71 meshes: read_relative(data, header.mesh_indexes())?,
72 switch_point: header.switch_point,
73 })
74 }
75}
76
77#[derive(Debug, Clone)]
78pub struct Mesh {
79 pub strip_groups: Vec<StripGroup>,
80 pub flags: MeshFlags,
81}
82
83impl ReadRelative for Mesh {
84 type Header = MeshHeader;
85
86 fn read(data: &[u8], header: Self::Header) -> Result<Self> {
87 Ok(Mesh {
88 strip_groups: read_relative(data, header.strip_group_indexes())?,
89 flags: header.flags,
90 })
91 }
92}
93
94#[derive(Debug, Clone)]
95pub struct StripGroup {
96 pub indices: Vec<u16>,
98 pub vertices: Vec<Vertex>,
99 pub strips: Vec<Strip>,
100 pub flags: StripGroupFlags,
101}
102
103impl ReadRelative for StripGroup {
104 type Header = StripGroupHeader;
105
106 fn read(data: &[u8], header: Self::Header) -> Result<Self> {
107 Ok(StripGroup {
108 vertices: read_relative(data, header.vertex_indexes())?,
109 strips: read_relative(data, header.strip_indexes())?,
110 indices: read_relative(data, header.index_indexes())?,
111 flags: header.flags,
112 })
113 }
114}
115
116#[derive(Debug, Clone)]
117pub struct Strip {
118 vertices: Range<usize>,
120 pub flags: StripFlags,
121 indices: Range<usize>,
122}
123
124impl ReadRelative for Strip {
125 type Header = StripHeader;
126
127 fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
128 Ok(Strip {
129 vertices: header.vertex_indexes(),
130 indices: header.index_indexes(),
131 flags: header.flags,
132 })
133 }
134}
135
136impl Strip {
137 pub fn vertices(&self) -> impl Iterator<Item = usize> + 'static {
138 self.vertices.clone()
139 }
140
141 pub fn indices(&self) -> impl Iterator<Item = usize> + 'static {
142 if self.flags.contains(StripFlags::IS_TRI_STRIP) {
143 let offset = self.indices.start;
144 Either::Left((0..self.indices.len()).flat_map(move |i| {
145 let cw = i & 1;
146 let idx = offset + i;
147 [idx, idx + 1 - cw, idx + 2 - cw].into_iter().rev()
148 }))
149 } else {
150 Either::Right(self.indices.clone().rev())
151 }
152 }
153}