physis/
stm.rs

1// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use std::io::{Cursor, Seek, SeekFrom};
5
6use crate::ByteSpan;
7use binrw::BinRead;
8use binrw::{BinReaderExt, binrw};
9
10/// Maximum number of elements in one row
11const MAX_ELEMENTS: usize = 128;
12
13#[binrw]
14#[derive(Debug)]
15#[brw(little)]
16struct StmHeader {
17    #[br(pad_before = 4)] // TODO: what is this byte?
18    entry_count: i32,
19
20    #[br(count = entry_count)]
21    keys: Vec<u16>,
22
23    #[br(count = entry_count)]
24    offsets: Vec<u16>,
25}
26
27#[derive(Debug)]
28#[allow(dead_code)]
29pub struct DyePack {
30    diffuse: [f32; 3],
31    specular: [f32; 3],
32    emissive: [f32; 3],
33    gloss: f32,
34    specular_power: f32,
35}
36
37#[derive(Debug)]
38pub struct StainingTemplate {}
39
40impl StainingTemplate {
41    /// Reads an existing ULD file
42    pub fn from_existing(buffer: ByteSpan) -> Option<Self> {
43        let mut cursor = Cursor::new(buffer);
44        let header = StmHeader::read(&mut cursor).unwrap();
45
46        for entry_offset in header.offsets {
47            let offset = entry_offset as i32 * 2 + 8 + 4 * header.entry_count;
48
49            // read the stm entry
50            cursor.seek(SeekFrom::Start(offset as u64)).ok()?;
51
52            // read the value offsets
53            let mut ends = [0u16; 5];
54            for end in &mut ends {
55                *end = cursor.read_le::<u16>().unwrap() * 2;
56            }
57
58            /*let new_offset = (offset + 10) as u64;
59
60            let diffuse_entries = StainingTemplate::read_array::<Half3>(&mut cursor, new_offset, ends[0] as usize);
61            let specular_entries = StainingTemplate::read_array::<Half3>(&mut cursor, new_offset + ends[0] as u64, ends[1] as usize - ends[0] as usize);
62            let emissive_entries = StainingTemplate::read_array::<Half3>(&mut cursor, new_offset + ends[1] as u64, ends[2] as usize - ends[1] as usize);
63            let gloss_entries = StainingTemplate::read_array::<Half1>(&mut cursor, new_offset + ends[2] as u64, ends[3] as usize - ends[2] as usize);
64            let specular_power_entries = StainingTemplate::read_array::<Half1>(&mut cursor, new_offset + ends[3] as u64, ends[4] as usize - ends[3] as usize);*/
65        }
66
67        Some(StainingTemplate {})
68    }
69
70    #[allow(unused)]
71    fn read_array<T: binrw::BinRead<Args<'static> = ()> + Default + Clone + Copy>(
72        cursor: &mut Cursor<ByteSpan>,
73        offset: u64,
74        size: usize,
75    ) -> Vec<T> {
76        cursor.seek(SeekFrom::Start(offset)).unwrap();
77
78        let array_size = size / std::mem::size_of::<T>();
79        if array_size == 0 {
80            vec![T::default(); MAX_ELEMENTS]
81        } else if array_size == 1 {
82            let element = cursor.read_le::<T>().unwrap();
83            vec![element; MAX_ELEMENTS]
84        } else if array_size < MAX_ELEMENTS {
85            let real_count = array_size - MAX_ELEMENTS / std::mem::size_of::<T>();
86            let mut values = vec![];
87            let mut indices = vec![];
88            values.push(T::default());
89            for _ in 0..real_count {
90                values.push(cursor.read_le::<T>().unwrap());
91            }
92
93            let eof_marker = cursor.read_le::<u8>().unwrap();
94            assert_eq!(eof_marker, 0xFF);
95
96            for _ in 0..MAX_ELEMENTS {
97                indices.push(cursor.read_le::<u8>().unwrap());
98            }
99
100            let mut vec = vec![];
101            for index in indices {
102                if (index as usize) < values.len() {
103                    vec.push(values[index as usize]);
104                } else {
105                    vec.push(T::default());
106                }
107            }
108
109            vec
110        } else if array_size == MAX_ELEMENTS {
111            let mut vec = vec![];
112            for _ in 0..size {
113                vec.push(cursor.read_le::<T>().unwrap());
114            }
115            vec
116        } else {
117            panic!("Too many elements");
118        }
119    }
120}