wgtk/model/
primitive.rs

1//! Utilities to read primitives processed files.
2
3use 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
12/// Magic of a primitives processed files.
13pub const MAGIC: &[u8; 4] = b"\x65\x4E\xA1\x42";
14
15
16/// Trait to implement for section codecs.
17pub trait Section: Sized {
18
19    /// Read this section from the given reader, this reader
20    /// is seekable and its cursor will be located at the 
21    /// beginning of the section. The length of the section
22    /// is also given.
23    fn read<R: Read + Seek>(reader: R, len: usize) -> Result<Self, DeError>;
24
25}
26
27
28/// Primitive store reader utility.
29pub struct PrimitiveReader<R> {
30    inner: R,
31    sections: HashMap<String, SectionMeta>,
32}
33
34impl<R> PrimitiveReader<R> {
35
36    /// Consume the primitive reader and 
37    #[inline]
38    pub fn into_inner(self) -> R {
39        self.inner
40    }
41
42}
43
44impl<R: Read + Seek> PrimitiveReader<R> {
45
46    /// Open and decode a prititives file's header, the reader is
47    /// kept open and date can be read.
48    /// 
49    /// *The position of the reader is not important because it
50    /// will be forced to zero before reading. It works like that 
51    /// because the inner reader will be read in absolute
52    /// positionning.*
53    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            // Keep the alignment of the section offset.
82            section_offset += section_len;
83            if section_len % 4 != 0 {
84                section_offset += 4 - section_len % 4;
85            }
86            
87            // Keep the alignment of the table cursor.
88            table_len -= 24; // Remove the two u32 and the 16 skept bytes.
89            table_len -= section_name_len; // Remove the size of the name.
90            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; // Also remove the padding from the current length.
95            }
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    /// Read the given section using the given section type.
117    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/// Metadata about a section in the primitive file.
129#[derive(Debug)]
130pub struct SectionMeta {
131    pub name: String,
132    pub off: usize,
133    pub len: usize,
134}
135
136
137/// A section that contains vertices.
138#[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        // Read the type of vertex. This type is a null-terminated string
148        // of a fixed length of 64 octets.
149        let mut ty_name = reader.read_cstring(64)?;
150        let mut count = reader.read_u32()?;
151
152        // Modern types contains 'BPVT', in such cases the real vertex 
153        // type is located after the first one.
154        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        // Set the following properties depending on the given vertex
162        // type. This is used to know how to read individual vertex.
163        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        // Read all vertices.
195        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                // Read indices and divide by 3.
254                reader.read_exact(&mut index[..])?;
255                index[0] /= 3;
256                index[1] /= 3;
257                index[2] /= 3;
258
259                if ty_new {
260                    // New indices need to be swapped.
261                    index.swap(0, 2);
262                    // Unknown purpose.
263                    reader.read_exact(&mut index2[..])?;
264                }
265
266                // Read 2 weights and compute third one. 
267                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/// A section that contains indices and groups.
322#[derive(Debug)]
323pub struct Indices {
324    /// Listing of all primitives (triangles).
325    pub primitives: Vec<Primitive>,
326    /// Listing of all groups of primitives.
327    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        // Get the type name and the indices' width.
335        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        // Read number of vertices and groups.
343        let vertices_count = reader.read_u32()? / 3;
344        let groups_count = reader.read_u32()?;
345
346        // Read all indices.
347        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/// A primitive (triangle) of indices, referencing vertices.
383#[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    /// Offset of the first primitive of this group.
393    pub primitives_offset: u32,
394    /// Number of primitives in the group.
395    pub primitives_count: u32,
396    /// Offset of the first vertex of this group.
397    pub vertices_offset: u32,
398    /// Number of vertices in the group.
399    pub vertices_count: u32,
400}
401
402
403/// Deserialization errors that can happen while deserializing sections.
404#[derive(Debug)]
405pub enum DeError {
406    /// Invalid magic signature for the file.
407    InvalidMagic,
408    /// Any section's type begins with a type describing data layout for
409    /// the section. This error is returned if such type cannot be resolved.
410    InvalidType(String),
411    /// Unhandled underlying I/O error.
412    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}