1use std::io::{self, Read, Seek, SeekFrom};
4use std::collections::HashMap;
5use std::fmt;
6
7use glam::{Vec3, Vec2};
8
9use crate::util::io::{WgReadExt};
10
11
12pub const MAGIC: &[u8; 4] = b"\x65\x4E\xA1\x42";
14
15
16pub trait Section: Sized {
18
19 fn read<R: Read + Seek>(reader: R, len: usize) -> Result<Self, DeError>;
24
25}
26
27
28pub struct PrimitiveReader<R> {
30 inner: R,
31 sections: HashMap<String, SectionMeta>,
32}
33
34impl<R> PrimitiveReader<R> {
35
36 #[inline]
38 pub fn into_inner(self) -> R {
39 self.inner
40 }
41
42}
43
44impl<R: Read + Seek> PrimitiveReader<R> {
45
46 pub fn open(mut inner: R) -> Result<Self, DeError> {
54
55 let mut sections = HashMap::new();
56
57 inner.rewind()?;
58 if !inner.check_exact(MAGIC)? {
59 return Err(DeError::InvalidMagic);
60 }
61
62 inner.seek(SeekFrom::End(-4))?;
63 let mut table_len = inner.read_u32()? as usize;
64 inner.seek(SeekFrom::End(-4 - table_len as i64))?;
65
66 let mut section_offset = 4;
67
68 while table_len != 0 {
69
70 let section_len = inner.read_u32()? as usize;
71 inner.skip::<16>()?;
72 let section_name_len = inner.read_u32()? as usize;
73 let section_name = inner.read_string(section_name_len)?;
74
75 sections.insert(section_name.clone(), SectionMeta {
76 name: section_name,
77 off: section_offset,
78 len: section_len,
79 });
80
81 section_offset += section_len;
83 if section_len % 4 != 0 {
84 section_offset += 4 - section_len % 4;
85 }
86
87 table_len -= 24; table_len -= section_name_len; if section_name_len % 4 != 0 {
91 let pad = 4 - section_name_len % 4;
92 let mut buf = [0; 4];
93 inner.read_exact(&mut buf[..pad])?;
94 table_len -= pad; }
96
97 }
98
99 Ok(Self {
100 inner,
101 sections,
102 })
103
104 }
105
106 #[inline]
107 pub fn iter_sections_meta(&self) -> impl Iterator<Item = &'_ SectionMeta> {
108 self.sections.values()
109 }
110
111 #[inline]
112 pub fn get_section_meta(&self, name: &str) -> Option<&SectionMeta> {
113 self.sections.get(name)
114 }
115
116 pub fn read_section<S: Section>(&mut self, name: &str) -> Option<Result<S, DeError>> {
118 let &SectionMeta { off, len, .. } = self.get_section_meta(name)?;
119 match self.inner.seek(SeekFrom::Start(off as u64)) {
120 Ok(_) => Some(S::read(&mut self.inner, len)),
121 Err(e) => Some(Err(e.into()))
122 }
123 }
124
125}
126
127
128#[derive(Debug)]
130pub struct SectionMeta {
131 pub name: String,
132 pub off: usize,
133 pub len: usize,
134}
135
136
137#[derive(Debug)]
139pub struct Vertices {
140 pub vertices: Vec<Vertex>,
141}
142
143impl Section for Vertices {
144
145 fn read<R: Read + Seek>(mut reader: R, _len: usize) -> Result<Self, DeError> {
146
147 let mut ty_name = reader.read_cstring(64)?;
150 let mut count = reader.read_u32()?;
151
152 if ty_name.starts_with("BPVT") {
155 ty_name = reader.read_cstring(64)?;
156 count = reader.read_u32()?;
157 }
158
159 let mut vertices = Vec::new();
160
161 let mut ty_new = false;
164 let mut ty_skinned = false;
165 let mut ty_tb = false;
166 let mut ty_iiiww = false;
167
168 match &ty_name[..] {
169 "set3/xyznuvtbpc" => {
170 ty_new = true;
171 ty_tb = true;
172 }
173 "set3/xyznuvpc" => {
174 ty_new = true;
175 }
176 "set3/xyznuviiiwwtbpc" => {
177 ty_new = true;
178 ty_skinned = true;
179 ty_tb = true;
180 ty_iiiww = true;
181 }
182 "xyznuviiiwwtb" => {
183 ty_skinned = true;
184 ty_tb = true;
185 ty_iiiww = true;
186 }
187 "xyznuvtb" => {
188 ty_tb = true;
189 }
190 "xyznuv" => {}
191 _ => return Err(DeError::InvalidType(ty_name))
192 }
193
194 for _ in 0..count {
196
197 let position = {
198 let x = reader.read_f32()?;
199 let y = reader.read_f32()?;
200 let z = reader.read_f32()?;
201 Vec3::new(x, if ty_skinned { -y } else { y }, z)
202 };
203
204 let normal = {
205 let packed = reader.read_u32()?;
206 if ty_new {
207
208 #[inline(always)]
209 fn p2f(n: u32) -> f32 {
210 if n > 0x7F {
211 -((n & 0x7F) as f32) / 0x7F as f32
212 } else {
213 (n ^ 0x7F) as f32 / 0x7F as f32
214 }
215 }
216
217 let pkz = (packed >> 16) & 0xFF ^ 0xFF;
218 let pky = (packed >> 8) & 0xFF ^ 0xFF;
219 let pkx = packed & 0xFF ^ 0xFF;
220 Vec3::new(p2f(pkx), p2f(pky), p2f(pkz))
221
222 } else {
223
224 #[inline(always)]
225 fn p2f(n: u32, a: u32) -> f32 {
226 if n > a {
227 -(((n & a ^ a) + 1) as f32) / a as f32
228 } else {
229 n as f32 / a as f32
230 }
231 }
232
233 let pkz = (packed >> 22) & 0x3FF;
234 let pky = (packed >> 11) & 0x7FF;
235 let pkx = packed & 0x7FF;
236 Vec3::new(p2f(pkx, 0x3FF), p2f(pky, 0x3FF), p2f(pkz, 0x1FF))
237
238 }
239 };
240
241 let uv = {
242 let u = reader.read_f32()?;
243 let v = reader.read_f32()?;
244 Vec2::new(u, 1.0 - v)
245 };
246
247 let mut index = [0; 3];
248 let mut index2 = [0; 3];
249 let mut weight = [0.0; 3];
250
251 if ty_iiiww {
252
253 reader.read_exact(&mut index[..])?;
255 index[0] /= 3;
256 index[1] /= 3;
257 index[2] /= 3;
258
259 if ty_new {
260 index.swap(0, 2);
262 reader.read_exact(&mut index2[..])?;
264 }
265
266 weight[0] = reader.read_u8()? as f32 / 255.0;
268 weight[1] = reader.read_u8()? as f32 / 255.0;
269 weight[2] = 1.0 - weight[0] - weight[1];
270
271 }
272
273 let tangent = if ty_tb { reader.read_u32()? } else { 0 };
274 let binormal = if ty_tb { reader.read_u32()? } else { 0 };
275
276 vertices.push(Vertex {
277 position,
278 normal,
279 uv,
280 index,
281 index2,
282 weight,
283 tangent,
284 binormal,
285 });
286
287 }
288
289 Ok(Self { vertices })
290
291 }
292
293}
294
295pub struct Vertex {
296 pub position: Vec3,
297 pub normal: Vec3,
298 pub uv: Vec2,
299 pub index: [u8; 3],
300 pub index2: [u8; 3],
301 pub weight: [f32; 3],
302 pub tangent: u32,
303 pub binormal: u32,
304}
305
306impl fmt::Debug for Vertex {
307 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308 write!(f, "Vertex {{ pos: {}/{}/{}, norm: {}/{}/{}, uv: {}/{}, index: {:?}, weight: {:?}, tan: {}, binorm: {} }}",
309 self.position.x, self.position.y, self.position.z,
310 self.normal.x, self.normal.y, self.normal.z,
311 self.uv.x, self.uv.y,
312 self.index,
313 self.weight,
314 self.tangent,
315 self.binormal,
316 )
317 }
318}
319
320
321#[derive(Debug)]
323pub struct Indices {
324 pub primitives: Vec<Primitive>,
326 pub groups: Vec<Group>,
328}
329
330impl Section for Indices {
331
332 fn read<R: Read + Seek>(mut reader: R, _len: usize) -> Result<Self, DeError> {
333
334 let ty_name = reader.read_cstring(64)?;
336 let ty_long = match &ty_name[..] {
337 "list" => false,
338 "list32" => true,
339 _ => return Err(DeError::InvalidType(ty_name))
340 };
341
342 let vertices_count = reader.read_u32()? / 3;
344 let groups_count = reader.read_u32()?;
345
346 let mut indices = Vec::new();
348 if ty_long {
349 for _ in 0..vertices_count {
350 indices.push(Primitive {
351 a: reader.read_u32()?,
352 b: reader.read_u32()?,
353 c: reader.read_u32()?,
354 });
355 }
356 } else {
357 for _ in 0..vertices_count {
358 indices.push(Primitive {
359 a: reader.read_u16()? as u32,
360 b: reader.read_u16()? as u32,
361 c: reader.read_u16()? as u32,
362 });
363 }
364 }
365
366 let mut groups = Vec::new();
367 for _ in 0..groups_count {
368 groups.push(Group {
369 primitives_offset: reader.read_u32()?,
370 primitives_count: reader.read_u32()?,
371 vertices_offset: reader.read_u32()?,
372 vertices_count: reader.read_u32()?,
373 });
374 }
375
376 Ok(Self { primitives: indices, groups })
377
378 }
379
380}
381
382#[derive(Debug)]
384pub struct Primitive {
385 pub a: u32,
386 pub b: u32,
387 pub c: u32,
388}
389
390#[derive(Debug)]
391pub struct Group {
392 pub primitives_offset: u32,
394 pub primitives_count: u32,
396 pub vertices_offset: u32,
398 pub vertices_count: u32,
400}
401
402
403#[derive(Debug)]
405pub enum DeError {
406 InvalidMagic,
408 InvalidType(String),
411 Io(io::Error),
413}
414
415impl fmt::Display for DeError {
416 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417 match *self {
418 Self::InvalidMagic => write!(f, "invalid magic"),
419 Self::InvalidType(ref s) => write!(f, "invalid type '{s}'"),
420 Self::Io(ref err) => write!(f, "io error: {err}"),
421 }
422 }
423}
424
425impl std::error::Error for DeError {
426 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
427 match self {
428 Self::Io(err) => Some(err),
429 _ => None
430 }
431 }
432}
433
434impl From<io::Error> for DeError {
435 fn from(e: io::Error) -> Self {
436 Self::Io(e)
437 }
438}