1use anyhow::Result;
9use std::io::Read;
10use super::prp::PlasmaRead;
11
12const POS_QUANTUM: f32 = 1.0 / 1024.0; const WEIGHT_QUANTUM: f32 = 1.0 / 32768.0; const UVW_QUANTUM: f32 = 1.0 / 65536.0; const QUANTA: [f32; 10] = [
18 POS_QUANTUM, WEIGHT_QUANTUM, UVW_QUANTUM, UVW_QUANTUM, UVW_QUANTUM, UVW_QUANTUM, UVW_QUANTUM, UVW_QUANTUM, UVW_QUANTUM, UVW_QUANTUM, ];
23
24const FIELD_POSITION: usize = 0;
25const FIELD_WEIGHT: usize = 1;
26const FIELD_UVW: usize = 2;
27
28const SAME_MASK: u16 = 0x8000;
29
30struct FloatState {
31 offset: f32,
32 all_same: bool,
33 count: u16,
34}
35
36struct ByteState {
37 count: u16,
38 val: u8,
39 same: bool,
40}
41
42pub struct VertCoder {
43 floats: [[FloatState; 3]; 10],
44 colors: [ByteState; 4],
45}
46
47impl VertCoder {
48 pub fn new() -> Self {
49 Self {
50 floats: std::array::from_fn(|_| std::array::from_fn(|_| FloatState {
51 offset: 0.0, all_same: false, count: 0,
52 })),
53 colors: std::array::from_fn(|_| ByteState {
54 count: 0, val: 0, same: false,
55 }),
56 }
57 }
58
59 fn decode_float(&mut self, reader: &mut impl Read, field: usize, chan: usize,
60 dst: &mut [u8], offset: &mut usize) -> Result<()> {
61 if self.floats[field][chan].count == 0 {
62 self.floats[field][chan].offset = reader.read_f32()?;
64
65 let all_same = reader.read_u8()?;
66 self.floats[field][chan].all_same = all_same != 0;
67
68 self.floats[field][chan].count = reader.read_u16()?;
69 }
70
71 if self.floats[field][chan].all_same {
72 let bytes = self.floats[field][chan].offset.to_le_bytes();
74 dst[*offset..*offset + 4].copy_from_slice(&bytes);
75 } else {
76 let ival = reader.read_u16()?;
78 let fval = ival as f32 * QUANTA[field] + self.floats[field][chan].offset;
79 let bytes = fval.to_le_bytes();
80 dst[*offset..*offset + 4].copy_from_slice(&bytes);
81 }
82
83 *offset += 4;
84 self.floats[field][chan].count = self.floats[field][chan].count.saturating_sub(1);
85 Ok(())
86 }
87
88 fn decode_normal(&mut self, reader: &mut impl Read, dst: &mut [u8], offset: &mut usize) -> Result<()> {
89 for _ in 0..3 {
92 let byte = reader.read_u8()?;
93 let val = (byte as f32 / 255.9 - 0.5) * 2.0;
94 dst[*offset..*offset + 4].copy_from_slice(&val.to_le_bytes());
95 *offset += 4;
96 }
97 Ok(())
98 }
99
100 fn decode_byte(&mut self, reader: &mut impl Read, chan: usize, dst: &mut [u8], offset: &mut usize) -> Result<()> {
101 if self.colors[chan].count == 0 {
102 let cnt = reader.read_u16()?;
103 if cnt & SAME_MASK != 0 {
104 self.colors[chan].same = true;
105 self.colors[chan].val = reader.read_u8()?;
106 self.colors[chan].count = cnt & !SAME_MASK;
107 } else {
108 self.colors[chan].same = false;
109 self.colors[chan].count = cnt;
110 }
111 }
112
113 if !self.colors[chan].same {
114 dst[*offset] = reader.read_u8()?;
115 } else {
116 dst[*offset] = self.colors[chan].val;
117 }
118
119 *offset += 1;
120 self.colors[chan].count = self.colors[chan].count.saturating_sub(1);
121 Ok(())
122 }
123
124 fn decode_color(&mut self, reader: &mut impl Read, dst: &mut [u8], offset: &mut usize) -> Result<()> {
125 self.decode_byte(reader, 0, dst, offset)?;
126 self.decode_byte(reader, 1, dst, offset)?;
127 self.decode_byte(reader, 2, dst, offset)?;
128 self.decode_byte(reader, 3, dst, offset)?;
129 Ok(())
130 }
131
132 fn decode_vertex(&mut self, reader: &mut impl Read, dst: &mut [u8], offset: &mut usize,
133 format: u8) -> Result<()> {
134 self.decode_float(reader, FIELD_POSITION, 0, dst, offset)?;
136 self.decode_float(reader, FIELD_POSITION, 1, dst, offset)?;
137 self.decode_float(reader, FIELD_POSITION, 2, dst, offset)?;
138
139 let num_weights = ((format & 0x30) >> 4) as usize;
141 for j in 0..num_weights {
142 self.decode_float(reader, FIELD_WEIGHT, j, dst, offset)?;
143 }
144 if format & 0x40 != 0 {
146 let idx = reader.read_u32()?;
147 dst[*offset..*offset + 4].copy_from_slice(&idx.to_le_bytes());
148 *offset += 4;
149 }
150
151 self.decode_normal(reader, dst, offset)?;
153
154 self.decode_color(reader, dst, offset)?;
156
157 dst[*offset..*offset + 4].copy_from_slice(&[0u8; 4]);
159 *offset += 4;
160
161 let num_uvws = (format & 0x0F) as usize;
163 for i in 0..num_uvws {
164 self.decode_float(reader, FIELD_UVW + i, 0, dst, offset)?;
165 self.decode_float(reader, FIELD_UVW + i, 1, dst, offset)?;
166 self.decode_float(reader, FIELD_UVW + i, 2, dst, offset)?;
167 }
168
169 Ok(())
170 }
171
172 pub fn read(&mut self, reader: &mut impl Read, format: u8, stride: usize,
175 num_verts: u16) -> Result<Vec<u8>> {
176 let total_size = num_verts as usize * stride;
177 let mut data = vec![0u8; total_size];
178
179 for i in 0..num_verts as usize {
180 let mut offset = i * stride;
181 if let Err(e) = self.decode_vertex(reader, &mut data, &mut offset, format) {
182 if i == 0 {
183 return Err(e);
185 }
186 log::warn!("Vertex decode failed at vertex {}/{}: {}, returning partial data",
187 i, num_verts, e);
188 data.truncate(i * stride);
190 return Ok(data);
191 }
192 }
193
194 Ok(data)
195 }
196}