1use crate::ByteSpan;
5use crate::model::MDL;
6use binrw::{BinReaderExt, BinResult, BinWriterExt};
7use half::f16;
8use std::io::Cursor;
9
10const MAX_BYTE_FLOAT: f32 = u8::MAX as f32;
12
13impl MDL {
14 pub(crate) fn read_byte_float4(cursor: &mut Cursor<ByteSpan>) -> Option<[f32; 4]> {
15 Some([
16 (f32::from(cursor.read_le::<u8>().ok()?) / MAX_BYTE_FLOAT),
17 (f32::from(cursor.read_le::<u8>().ok()?) / MAX_BYTE_FLOAT),
18 (f32::from(cursor.read_le::<u8>().ok()?) / MAX_BYTE_FLOAT),
19 (f32::from(cursor.read_le::<u8>().ok()?) / MAX_BYTE_FLOAT),
20 ])
21 }
22
23 pub(crate) fn write_byte_float4<T: BinWriterExt>(
24 cursor: &mut T,
25 vec: &[f32; 4],
26 ) -> BinResult<()> {
27 cursor.write_le::<[u8; 4]>(&[
28 (vec[0] * MAX_BYTE_FLOAT).round() as u8,
29 (vec[1] * MAX_BYTE_FLOAT).round() as u8,
30 (vec[2] * MAX_BYTE_FLOAT).round() as u8,
31 (vec[3] * MAX_BYTE_FLOAT).round() as u8,
32 ])
33 }
34
35 pub(crate) fn write_byte_float42<T: BinWriterExt>(
36 cursor: &mut T,
37 vec: &[f32; 4],
38 ) -> BinResult<()> {
39 cursor.write_le::<[u8; 4]>(&[
40 (vec[0]).round() as u8,
41 (vec[1]).round() as u8,
42 (vec[2]).round() as u8,
43 (vec[3]).round() as u8,
44 ])
45 }
46
47 pub(crate) fn read_tangent(cursor: &mut Cursor<ByteSpan>) -> Option<[f32; 4]> {
48 Some([
49 (f32::from(cursor.read_le::<u8>().ok()?) * 2.0 / MAX_BYTE_FLOAT - 1.0),
50 (f32::from(cursor.read_le::<u8>().ok()?) * 2.0 / MAX_BYTE_FLOAT - 1.0),
51 (f32::from(cursor.read_le::<u8>().ok()?) * 2.0 / MAX_BYTE_FLOAT - 1.0),
52 if (f32::from(cursor.read_le::<u8>().ok()?) * 2.0 / MAX_BYTE_FLOAT - 1.0) == 1.0 {
53 1.0
54 } else {
55 -1.0
56 },
57 ])
58 }
59
60 pub(crate) fn write_tangent<T: BinWriterExt>(cursor: &mut T, vec: &[f32; 4]) -> BinResult<()> {
61 cursor.write_le::<[u8; 4]>(&[
62 ((vec[0] + 1.0) * (MAX_BYTE_FLOAT / 2.0)).round() as u8,
63 ((vec[1] + 1.0) * (MAX_BYTE_FLOAT / 2.0)).round() as u8,
64 ((vec[2] + 1.0) * (MAX_BYTE_FLOAT / 2.0)).round() as u8,
65 if vec[3] > 0.0 { 255 } else { 0 },
66 ]) }
68
69 pub(crate) fn read_half4(cursor: &mut Cursor<ByteSpan>) -> Option<[f32; 4]> {
70 Some([
71 f16::from_bits(cursor.read_le::<u16>().ok()?).to_f32(),
72 f16::from_bits(cursor.read_le::<u16>().ok()?).to_f32(),
73 f16::from_bits(cursor.read_le::<u16>().ok()?).to_f32(),
74 f16::from_bits(cursor.read_le::<u16>().ok()?).to_f32(),
75 ])
76 }
77
78 pub(crate) fn write_half4<T: BinWriterExt>(cursor: &mut T, vec: &[f32; 4]) -> BinResult<()> {
79 cursor.write_le::<[u16; 4]>(&[
80 f16::from_f32(vec[0]).to_bits(),
81 f16::from_f32(vec[1]).to_bits(),
82 f16::from_f32(vec[2]).to_bits(),
83 f16::from_f32(vec[3]).to_bits(),
84 ])
85 }
86
87 pub(crate) fn read_half2(cursor: &mut Cursor<ByteSpan>) -> Option<[f32; 2]> {
88 Some([
89 f16::from_bits(cursor.read_le::<u16>().ok()?).to_f32(),
90 f16::from_bits(cursor.read_le::<u16>().ok()?).to_f32(),
91 ])
92 }
93
94 #[allow(dead_code)] pub(crate) fn write_half2<T: BinWriterExt>(cursor: &mut T, vec: &[f32; 2]) -> BinResult<()> {
96 cursor.write_le::<[u16; 2]>(&[
97 f16::from_f32(vec[0]).to_bits(),
98 f16::from_f32(vec[1]).to_bits(),
99 ])
100 }
101
102 pub(crate) fn read_byte4(cursor: &mut Cursor<ByteSpan>) -> BinResult<[u8; 4]> {
103 cursor.read_le::<[u8; 4]>()
104 }
105
106 pub(crate) fn write_byte4<T: BinWriterExt>(cursor: &mut T, vec: &[u8; 4]) -> BinResult<()> {
107 cursor.write_le::<[u8; 4]>(vec)
108 }
109
110 pub(crate) fn read_single3(cursor: &mut Cursor<ByteSpan>) -> BinResult<[f32; 3]> {
111 cursor.read_le::<[f32; 3]>()
112 }
113
114 pub(crate) fn write_single3<T: BinWriterExt>(cursor: &mut T, vec: &[f32; 3]) -> BinResult<()> {
115 cursor.write_le::<[f32; 3]>(vec)
116 }
117
118 pub(crate) fn read_single4(cursor: &mut Cursor<ByteSpan>) -> BinResult<[f32; 4]> {
119 cursor.read_le::<[f32; 4]>()
120 }
121
122 pub(crate) fn write_single4<T: BinWriterExt>(cursor: &mut T, vec: &[f32; 4]) -> BinResult<()> {
123 cursor.write_le::<[f32; 4]>(vec)
124 }
125
126 pub(crate) fn read_unsigned_short4(cursor: &mut Cursor<ByteSpan>) -> BinResult<[u16; 4]> {
127 cursor.read_le::<[u16; 4]>()
128 }
129
130 pub(crate) fn pad_slice<const N: usize>(small_slice: &[f32; N], fill: f32) -> [f32; 4] {
131 let mut bigger_slice: [f32; 4] = [fill, fill, fill, fill];
132 bigger_slice[..N].copy_from_slice(&small_slice[..N]);
133 bigger_slice
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use crate::model::MDL;
140 use std::io::Cursor;
141
142 macro_rules! assert_delta {
143 ($x:expr, $y:expr, $d:expr) => {
144 for i in 0..4 {
145 if !($x[i] - $y[i] < $d || $y[i] - $x[i] < $d) {
146 panic!();
147 }
148 }
149 };
150 }
151
152 #[test]
153 fn byte_float4() {
154 let a = [0.0, 1.0, 0.5, 0.25];
155
156 let mut v = vec![];
157 let mut cursor = Cursor::new(&mut v);
158
159 MDL::write_byte_float4(&mut cursor, &a).unwrap();
160
161 let mut read_cursor = Cursor::new(v.as_slice());
162
163 let b = MDL::read_byte_float4(&mut read_cursor).unwrap();
164 assert_delta!(b, a, 0.1);
165 }
166
167 #[test]
168 fn half4() {
169 let a = [0.0, 1.0, 0.5, 0.25];
170
171 let mut v = vec![];
172 let mut cursor = Cursor::new(&mut v);
173
174 MDL::write_half4(&mut cursor, &a).unwrap();
175
176 let mut read_cursor = Cursor::new(v.as_slice());
177 assert_eq!(MDL::read_half4(&mut read_cursor).unwrap(), a);
178 }
179
180 #[test]
181 fn half2() {
182 let a = [0.0, 1.0];
183
184 let mut v = vec![];
185 let mut cursor = Cursor::new(&mut v);
186
187 MDL::write_half2(&mut cursor, &a).unwrap();
188
189 let mut read_cursor = Cursor::new(v.as_slice());
190 assert_eq!(MDL::read_half2(&mut read_cursor).unwrap(), a);
191 }
192
193 #[test]
194 fn uint() {
195 let a = [5u8, 0u8, 3u8, 15u8];
196
197 let mut v = vec![];
198 let mut cursor = Cursor::new(&mut v);
199
200 MDL::write_byte4(&mut cursor, &a).unwrap();
201
202 let mut read_cursor = Cursor::new(v.as_slice());
203 assert_eq!(MDL::read_byte4(&mut read_cursor).unwrap(), a);
204 }
205
206 #[test]
207 fn single3() {
208 let a = [3.0, 0.0, -1.0];
209
210 let mut v = vec![];
211 let mut cursor = Cursor::new(&mut v);
212
213 MDL::write_single3(&mut cursor, &a).unwrap();
214
215 let mut read_cursor = Cursor::new(v.as_slice());
216 assert_eq!(MDL::read_single3(&mut read_cursor).unwrap(), a);
217 }
218
219 #[test]
220 fn single4() {
221 let a = [3.0, 0.0, -1.0, 12.0];
222
223 let mut v = vec![];
224 let mut cursor = Cursor::new(&mut v);
225
226 MDL::write_single4(&mut cursor, &a).unwrap();
227
228 let mut read_cursor = Cursor::new(v.as_slice());
229 assert_eq!(MDL::read_single4(&mut read_cursor).unwrap(), a);
230 }
231
232 #[test]
233 fn tangent() {
234 let a = [1.0, 0.5, -0.5, 1.0];
235
236 let mut v = vec![];
237 let mut cursor = Cursor::new(&mut v);
238
239 MDL::write_tangent(&mut cursor, &a).unwrap();
240
241 let mut read_cursor = Cursor::new(v.as_slice());
242 let tangent = MDL::read_tangent(&mut read_cursor).unwrap();
243 assert_delta!(tangent, a, 0.001);
244 }
245
246 #[test]
247 fn pad_slice() {
248 let a = [3.0, 0.0, -1.0];
249 let b = [3.0, 0.0, -1.0, 1.0];
250
251 assert_eq!(MDL::pad_slice(&a, 1.0), b);
252 }
253}