rw_parser_rs/renderware/ifp/
ifp_parser.rs1use crate::renderware::rw_file::RwFile;
27use crate::renderware::common::types::{RwVector3, RwQuaternion};
28use std::io::Result;
29
30use serde::Serialize;
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
34pub enum IfpVersion {
35 ANP3,
37 ANPK,
39 UNSUPPORTED,
41}
42
43#[derive(Debug, Clone, PartialEq, Serialize)]
48pub struct RwIfp {
49 pub version: IfpVersion,
51 pub name: String,
53 pub animations: Vec<RwIfpAnimation>,
55}
56
57#[derive(Debug, Clone, PartialEq, Serialize)]
58pub struct RwIfpAnimation {
59 pub name: String,
60 pub bones: Vec<RwIfpBone>,
61}
62
63#[derive(Debug, Clone, PartialEq, Serialize)]
64pub struct RwIfpBone {
65 pub name: String,
66 pub keyframe_type: String,
67 pub use_bone_id: bool,
68 pub bone_id: i32,
69 pub keyframes: Vec<RwIfpKeyframe>,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
73pub struct RwIfpKeyframe {
74 pub time: f32,
75 pub position: RwVector3,
76 pub rotation: RwQuaternion,
77 pub scale: RwVector3,
78}
79
80pub struct IfpParser<'a> {
85 file: RwFile<'a>,
86}
87
88impl<'a> IfpParser<'a> {
89 pub fn new(buffer: &'a [u8]) -> Self {
95 IfpParser {
96 file: RwFile::new(buffer),
97 }
98 }
99
100 pub fn parse(&mut self) -> Result<RwIfp> {
110 let file_signature = self.file.get_stream().read_string(4)?;
111 self.file.get_stream().set_position(0);
112
113 match file_signature.as_str() {
114 "ANP3" => self.read_anp3(),
115 "ANPK" => self.read_anpk(),
116 _ => Err(std::io::Error::new(std::io::ErrorKind::Other, "Unsupported IFP version")),
117 }
118 }
119
120 fn read_anp3(&mut self) -> Result<RwIfp> {
121 self.file.get_stream().skip(4)?; let _size = self.file.get_stream().read_u32()?;
123 let name = self.file.get_stream().read_string(24)?;
124 let animations_count = self.file.get_stream().read_u32()?;
125 let mut animations = Vec::with_capacity(animations_count as usize);
126
127 for _ in 0..animations_count {
128 animations.push(self.read_anp3_animation()?);
129 }
130
131 Ok(RwIfp {
132 version: IfpVersion::ANP3,
133 name,
134 animations,
135 })
136 }
137
138 fn read_anp3_animation(&mut self) -> Result<RwIfpAnimation> {
139 let name = self.file.get_stream().read_string(24)?;
140 let bones_count = self.file.get_stream().read_u32()?;
141 self.file.get_stream().skip(8)?; let mut bones = Vec::with_capacity(bones_count as usize);
143
144 for _ in 0..bones_count {
145 bones.push(self.read_anp3_bone()?);
146 }
147
148 Ok(RwIfpAnimation { name, bones })
149 }
150
151 fn read_anp3_bone(&mut self) -> Result<RwIfpBone> {
152 let name = self.file.get_stream().read_string(24)?;
153 let keyframe_type_num = self.file.get_stream().read_u32()?;
154 let keyframes_count = self.file.get_stream().read_u32()?;
155 let keyframe_type = if keyframe_type_num == 4 { "KRT0" } else { "KR00" }.to_string();
156 let bone_id = self.file.get_stream().read_i32()?;
157 let mut keyframes = Vec::with_capacity(keyframes_count as usize);
158
159 for _ in 0..keyframes_count {
160 let qx = self.file.get_stream().read_i16()? as f32 / 4096.0;
161 let qy = self.file.get_stream().read_i16()? as f32 / 4096.0;
162 let qz = self.file.get_stream().read_i16()? as f32 / 4096.0;
163 let qw = self.file.get_stream().read_i16()? as f32 / 4096.0;
164 let time = self.file.get_stream().read_i16()? as f32;
165
166 let (px, py, pz) = if keyframe_type.as_bytes()[2] == b'T' {
167 (
168 self.file.get_stream().read_i16()? as f32 / 1024.0,
169 self.file.get_stream().read_i16()? as f32 / 1024.0,
170 self.file.get_stream().read_i16()? as f32 / 1024.0,
171 )
172 } else {
173 (0.0, 0.0, 0.0)
174 };
175
176 keyframes.push(RwIfpKeyframe {
177 time,
178 position: RwVector3 { x: px, y: py, z: pz },
179 rotation: RwQuaternion { w: qw, x: qx, y: qy, z: qz },
180 scale: RwVector3 { x: 1.0, y: 1.0, z: 1.0 },
181 });
182 }
183
184 Ok(RwIfpBone {
185 name,
186 keyframe_type,
187 use_bone_id: true,
188 bone_id,
189 keyframes,
190 })
191 }
192
193 fn read_anpk(&mut self) -> Result<RwIfp> {
194 self.file.get_stream().skip(4)?; let _size = self.file.get_stream().read_u32()?;
196 self.file.get_stream().skip(4)?; let info_len = self.file.get_stream().read_u32()?;
198 let animations_count = self.file.get_stream().read_u32()?;
199 let name = self.file.get_stream().read_string((info_len - 4) as usize)?;
200 let name_align_len = (4 - info_len % 4) % 4;
201 self.file.get_stream().skip(name_align_len as u64)?;
202
203 let mut animations = Vec::with_capacity(animations_count as usize);
204 for _ in 0..animations_count {
205 animations.push(self.read_anpk_animation()?);
206 }
207
208 Ok(RwIfp {
209 version: IfpVersion::ANPK,
210 name,
211 animations,
212 })
213 }
214
215 fn read_anpk_animation(&mut self) -> Result<RwIfpAnimation> {
216 self.file.get_stream().skip(4)?; let name_len = self.file.get_stream().read_u32()?;
218 let name = self.file.get_stream().read_string(name_len as usize)?;
219 self.file.get_stream().skip(((4 - name_len % 4) % 4) as u64)?;
220 self.file.get_stream().skip(16)?; let bones_count = self.file.get_stream().read_u32()?;
222 self.file.get_stream().skip(4)?; let mut bones = Vec::with_capacity(bones_count as usize);
225 for _ in 0..bones_count {
226 bones.push(self.read_anpk_bone()?);
227 }
228
229 Ok(RwIfpAnimation { name, bones })
230 }
231
232 fn read_anpk_bone(&mut self) -> Result<RwIfpBone> {
233 self.file.get_stream().skip(8)?; self.file.get_stream().skip(4)?; let anim_len = self.file.get_stream().read_u32()?;
236 let name = self.file.get_stream().read_string(28)?;
237 let keyframes_count = self.file.get_stream().read_u32()?;
238 self.file.get_stream().skip(8)?; let use_bone_id = anim_len == 44;
241 let bone_id = if use_bone_id {
242 self.file.get_stream().read_i32()?
243 } else {
244 self.file.get_stream().skip(8)?;
245 0
246 };
247
248 let mut keyframe_type = "K000".to_string();
249 let mut keyframes = Vec::new();
250
251 if keyframes_count > 0 {
252 keyframe_type = self.file.get_stream().read_string(4)?;
253 self.file.get_stream().skip(4)?; for _ in 0..keyframes_count {
256 let qx = self.file.get_stream().read_f32()?;
257 let qy = self.file.get_stream().read_f32()?;
258 let qz = self.file.get_stream().read_f32()?;
259 let qw = self.file.get_stream().read_f32()?;
260
261 let (px, py, pz) = if keyframe_type.as_bytes()[2] == b'T' {
262 (self.file.get_stream().read_f32()?, self.file.get_stream().read_f32()?, self.file.get_stream().read_f32()?)
263 } else {
264 (0.0, 0.0, 0.0)
265 };
266
267 let (sx, sy, sz) = if keyframe_type.as_bytes()[3] == b'S' {
268 (self.file.get_stream().read_f32()?, self.file.get_stream().read_f32()?, self.file.get_stream().read_f32()?)
269 } else {
270 (1.0, 1.0, 1.0)
271 };
272
273 let time = self.file.get_stream().read_f32()?;
274
275 keyframes.push(RwIfpKeyframe {
276 time,
277 position: RwVector3 { x: px, y: py, z: pz },
278 rotation: RwQuaternion { w: qw, x: qx, y: qy, z: qz },
279 scale: RwVector3 { x: sx, y: sy, z: sz },
280 });
281 }
282 }
283
284 Ok(RwIfpBone {
285 name,
286 keyframe_type,
287 use_bone_id,
288 bone_id,
289 keyframes,
290 })
291 }
292}