1use super::dff_model_type::DffModelType;
28use crate::renderware::common::types::{
29 RwColor, RwMatrix3, RwMatrix4, RwSphere, RwTextureCoordinate, RwTriangle, RwVector3, RwVector4,
30};
31use crate::renderware::rw_file::RwFile;
32use crate::renderware::rw_sections::RwSections;
33use crate::utils::rw_version::{unpack_version, RwVersion};
34use std::io::Result;
35use num::FromPrimitive;
36
37use serde::Serialize;
38
39#[derive(Debug, Clone, PartialEq, Serialize)]
44pub struct RwDff {
45 pub model_type: DffModelType,
47 pub version: String,
49 pub version_number: u32,
51 pub geometry_list: Option<RwGeometryList>,
53 pub frame_list: Option<RwFrameList>,
55 pub atomics: Vec<u32>,
57 pub dummies: Vec<String>,
59 pub anim_nodes: Vec<RwAnimNode>,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
64pub struct RwClump {
65 pub atomic_count: u32,
66 pub light_count: Option<u32>,
67 pub camera_count: Option<u32>,
68}
69
70#[derive(Debug, Clone, PartialEq, Serialize)]
71pub struct RwAnimNode {
72 pub bone_id: i32,
73 pub bones_count: i32,
74 pub bones: Vec<RwBone>,
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
78pub struct RwBone {
79 pub bone_id: i32,
80 pub bone_index: i32,
81 pub flags: i32,
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
85pub struct RwFrame {
86 pub rotation_matrix: RwMatrix3,
87 pub coordinates_offset: RwVector3,
88 pub parent_frame: i32,
89}
90
91#[derive(Debug, Clone, PartialEq, Serialize)]
92pub struct RwFrameList {
93 pub frame_count: u32,
94 pub frames: Vec<RwFrame>,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
98pub struct RwTexture {
99 pub texture_filtering: u8,
100 pub u_addressing: u8,
101 pub v_addressing: u8,
102 pub uses_mip_levels: bool,
103 pub texture_name: String,
104}
105
106#[derive(Debug, Clone, PartialEq, Serialize)]
107pub struct RwMaterial {
108 pub color: RwColor,
109 pub is_textured: bool,
110 pub ambient: Option<f32>,
111 pub specular: Option<f32>,
112 pub diffuse: Option<f32>,
113 pub texture: Option<RwTexture>,
114}
115
116#[derive(Debug, Clone, PartialEq, Serialize)]
117pub struct RwMaterialList {
118 pub material_instance_count: u32,
119 pub material_data: Vec<RwMaterial>,
120}
121
122#[derive(Debug, Clone, PartialEq, Serialize)]
123pub struct RwGeometry {
124 pub vertex_color_information: Vec<RwColor>,
125 pub texture_coordinates_count: u8,
126 pub texture_mapping_information: Vec<Vec<RwTextureCoordinate>>,
127 pub has_vertices: bool,
128 pub has_normals: bool,
129 pub triangle_information: Vec<RwTriangle>,
130 pub vertex_information: Vec<RwVector3>,
131 pub normal_information: Vec<RwVector3>,
132 pub bounding_sphere: Option<RwSphere>,
133 pub material_list: RwMaterialList,
134 pub bin_mesh: RwBinMesh,
135 pub skin: Option<RwSkin>,
136}
137
138#[derive(Debug, Clone, PartialEq, Serialize)]
139pub struct RwGeometryList {
140 pub geometric_object_count: u32,
141 pub geometries: Vec<RwGeometry>,
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
145pub struct RwAtomic {
146 pub frame_index: u32,
147 pub geometry_index: u32,
148 pub flags: u32,
149}
150
151#[derive(Debug, Clone, PartialEq, Serialize)]
152pub struct RwBinMesh {
153 pub mesh_count: u32,
154 pub meshes: Vec<RwMesh>,
155}
156
157#[derive(Debug, Clone, PartialEq, Serialize)]
158pub struct RwSkin {
159 pub bone_count: u8,
160 pub used_bone_count: u8,
161 pub max_weights_per_vertex: u8,
162 pub bone_vertex_indices: Vec<Vec<u8>>,
163 pub vertex_weights: Vec<Vec<f32>>,
164 pub inverse_bone_matrices: Vec<RwMatrix4>,
165}
166
167#[derive(Debug, Clone, PartialEq, Serialize)]
168pub struct RwMesh {
169 pub material_index: u32,
170 pub index_count: u32,
171 pub indices: Vec<u32>,
172}
173
174pub struct DffParser<'a> {
179 file: RwFile<'a>,
180}
181
182impl<'a> DffParser<'a> {
183 pub fn new(buffer: &'a [u8]) -> Self {
189 DffParser {
190 file: RwFile::new(buffer),
191 }
192 }
193
194 pub fn parse(&mut self) -> Result<RwDff> {
204 let mut version: Option<String> = None;
205 let mut version_number: Option<u32> = None;
206 let mut atomics: Vec<u32> = Vec::new();
207 let mut dummies: Vec<String> = Vec::new();
208 let mut anim_nodes: Vec<RwAnimNode> = Vec::new();
209 let mut geometry_list: Option<RwGeometryList> = None;
210 let mut frame_list: Option<RwFrameList> = None;
211
212 while self.file.get_stream().get_position() < self.file.get_stream().get_size() {
213 let header = self.file.read_section_header()?;
214
215 if header.section_type == 0 {
216 break;
217 }
218
219 if header.section_size == 0 {
220 continue;
221 }
222
223 let section_type_enum: Option<RwSections> = FromPrimitive::from_u32(header.section_type);
224
225 match section_type_enum {
226 Some(RwSections::RwClump) => {
227 version_number = Some(unpack_version(header.version_number));
228 version = Some(RwVersion::new().get_version_string(version_number.unwrap()).unwrap_or_default());
229 }
230 Some(RwSections::RwFrameList) => {
231 frame_list = Some(self.read_frame_list()?);
232 }
233 Some(RwSections::RwExtension) => {
234 let extension_header = self.file.read_section_header()?;
235 let extension_type_enum: Option<RwSections> = FromPrimitive::from_u32(extension_header.section_type);
236 match extension_type_enum {
237 Some(RwSections::RwNodeName) => {
238 dummies.push(self.file.get_stream().read_string(extension_header.section_size as usize)?);
239 }
240 Some(RwSections::RwAnim) => {
241 anim_nodes.push(self.read_anim_node()?);
242 }
243 _ => {
244 self.file.get_stream().skip(extension_header.section_size as u64)?;
245 }
246 }
247 }
248 Some(RwSections::RwGeometryList) => {
249 geometry_list = Some(self.read_geometry_list()?);
250 }
251 Some(RwSections::RwAtomic) => {
252 let atomic = self.read_atomic()?;
253 if atomics.len() <= atomic.geometry_index as usize {
254 atomics.resize(atomic.geometry_index as usize + 1, 0);
255 }
256 atomics[atomic.geometry_index as usize] = atomic.frame_index;
257 }
258 Some(RwSections::RwNodeName) => {
259 dummies.push(self.file.get_stream().read_string(header.section_size as usize)?);
260 }
261 Some(RwSections::RwAnim) => {
262 anim_nodes.push(self.read_anim_node()?);
263 }
264 _ => {
265 self.file.get_stream().skip(header.section_size as u64)?;
266 }
267 }
268 }
269
270 let model_type = if geometry_list.as_ref().map_or(false, |g| g.geometries.iter().any(|geo| geo.skin.is_some())) {
271 DffModelType::Skin
272 } else if dummies.iter().any(|d| d.to_lowercase().contains("wheel") || d.to_lowercase().contains("chassis")) {
273 DffModelType::Vehicle
274 } else {
275 DffModelType::Generic
276 };
277
278 Ok(RwDff {
279 model_type,
280 version: version.unwrap_or_default(),
281 version_number: version_number.unwrap_or_default(),
282 geometry_list,
283 frame_list,
284 atomics,
285 dummies,
286 anim_nodes,
287 })
288 }
289
290 fn read_frame_list(&mut self) -> Result<RwFrameList> {
291 self.file.read_section_header()?; let frame_count = self.file.get_stream().read_u32()?;
294 let mut frames = Vec::with_capacity(frame_count as usize);
295
296 for _ in 0..frame_count {
297 let rotation_matrix = RwMatrix3 {
298 right: RwVector3 {
299 x: self.file.get_stream().read_f32()?,
300 y: self.file.get_stream().read_f32()?,
301 z: self.file.get_stream().read_f32()?,
302 },
303 up: RwVector3 {
304 x: self.file.get_stream().read_f32()?,
305 y: self.file.get_stream().read_f32()?,
306 z: self.file.get_stream().read_f32()?,
307 },
308 at: RwVector3 {
309 x: self.file.get_stream().read_f32()?,
310 y: self.file.get_stream().read_f32()?,
311 z: self.file.get_stream().read_f32()?,
312 },
313 };
314
315 let coordinates_offset = RwVector3 {
316 x: self.file.get_stream().read_f32()?,
317 y: self.file.get_stream().read_f32()?,
318 z: self.file.get_stream().read_f32()?,
319 };
320
321 let parent_frame = self.file.get_stream().read_i32()?;
322 self.file.get_stream().skip(4)?; frames.push(RwFrame {
325 rotation_matrix,
326 coordinates_offset,
327 parent_frame,
328 });
329 }
330
331 Ok(RwFrameList {
332 frame_count,
333 frames,
334 })
335 }
336
337 fn read_atomic(&mut self) -> Result<RwAtomic> {
338 self.file.read_section_header()?; let frame_index = self.file.get_stream().read_u32()?;
341 let geometry_index = self.file.get_stream().read_u32()?;
342 let flags = self.file.get_stream().read_u32()?;
343
344 self.file.get_stream().skip(4)?; Ok(RwAtomic {
347 frame_index,
348 geometry_index,
349 flags,
350 })
351 }
352
353 fn read_geometry_list(&mut self) -> Result<RwGeometryList> {
354 let header = self.file.read_section_header()?; let geometric_object_count = self.file.get_stream().read_u32()?;
357 let mut geometries = Vec::with_capacity(geometric_object_count as usize);
358
359 for _ in 0..geometric_object_count {
360 self.file.read_section_header()?; self.file.read_section_header()?; let version_number = unpack_version(header.version_number);
363 geometries.push(self.read_geometry(version_number)?);
364 }
365
366 Ok(RwGeometryList {
367 geometric_object_count,
368 geometries,
369 })
370 }
371
372 fn read_geometry(&mut self, version_number: u32) -> Result<RwGeometry> {
373 let flags = self.file.get_stream().read_u16()?;
374 let texture_coordinates_count = self.file.get_stream().read_u8()?;
375 let _native_geometry_flags = self.file.get_stream().read_u8()?;
376 let triangle_count = self.file.get_stream().read_u32()?;
377 let vertex_count = self.file.get_stream().read_u32()?;
378 let _morph_target_count = self.file.get_stream().read_u32()?;
379
380 if version_number < 0x34000 {
381 self.file.get_stream().skip(12)?; }
383
384 let is_textured_uv1 = (flags & (1 << 2)) != 0;
385 let is_geometry_prelit = (flags & (1 << 3)) != 0;
386 let is_textured_uv2 = (flags & (1 << 7)) != 0;
387
388 let mut vertex_color_information = Vec::new();
389 if is_geometry_prelit {
390 for _ in 0..vertex_count {
391 vertex_color_information.push(RwColor {
392 r: self.file.get_stream().read_u8()?,
393 g: self.file.get_stream().read_u8()?,
394 b: self.file.get_stream().read_u8()?,
395 a: self.file.get_stream().read_u8()?,
396 });
397 }
398 }
399
400 let mut texture_mapping_information = Vec::new();
401 if is_textured_uv1 || is_textured_uv2 {
402 for _ in 0..texture_coordinates_count {
403 let mut tex_coords = Vec::new();
404 for _ in 0..vertex_count {
405 tex_coords.push(RwTextureCoordinate {
406 u: self.file.get_stream().read_f32()?,
407 v: self.file.get_stream().read_f32()?,
408 });
409 }
410 texture_mapping_information.push(tex_coords);
411 }
412 }
413
414 let mut triangle_information = Vec::new();
415 for _ in 0..triangle_count {
416 let vertex2 = self.file.get_stream().read_u16()?;
417 let vertex1 = self.file.get_stream().read_u16()?;
418 let material_id = self.file.get_stream().read_u16()?;
419 let vertex3 = self.file.get_stream().read_u16()?;
420 triangle_information.push(RwTriangle {
421 vector: RwVector3 {
422 x: vertex1 as f32,
423 y: vertex2 as f32,
424 z: vertex3 as f32,
425 },
426 material_id,
427 });
428 }
429
430 let bounding_sphere = Some(RwSphere {
431 vector: RwVector3 {
432 x: self.file.get_stream().read_f32()?,
433 y: self.file.get_stream().read_f32()?,
434 z: self.file.get_stream().read_f32()?,
435 },
436 radius: self.file.get_stream().read_f32()?,
437 });
438
439 let has_vertices = self.file.get_stream().read_u32()? != 0;
440 let has_normals = self.file.get_stream().read_u32()? != 0;
441
442 let mut vertex_information = Vec::new();
443 if has_vertices {
444 for _ in 0..vertex_count {
445 vertex_information.push(RwVector3 {
446 x: self.file.get_stream().read_f32()?,
447 y: self.file.get_stream().read_f32()?,
448 z: self.file.get_stream().read_f32()?,
449 });
450 }
451 }
452
453 let mut normal_information = Vec::new();
454 if has_normals {
455 for _ in 0..vertex_count {
456 normal_information.push(RwVector3 {
457 x: self.file.get_stream().read_f32()?,
458 y: self.file.get_stream().read_f32()?,
459 z: self.file.get_stream().read_f32()?,
460 });
461 }
462 }
463
464 let material_list = self.read_material_list()?;
465 let section_size = self.file.read_section_header()?.section_size;
466 let position = self.file.get_stream().get_position();
467 let bin_mesh = self.read_bin_mesh()?;
468
469 let mut skin = None;
470 let next_header = self.file.read_section_header()?;
471 if next_header.section_type == RwSections::RwSkin as u32 {
472 skin = Some(self.read_skin(vertex_count)?);
473 }
474
475 self.file.get_stream().set_position(position + section_size as u64);
476
477 Ok(RwGeometry {
478 vertex_color_information,
479 texture_coordinates_count,
480 texture_mapping_information,
481 has_vertices,
482 has_normals,
483 triangle_information,
484 vertex_information,
485 normal_information,
486 bounding_sphere,
487 material_list,
488 bin_mesh,
489 skin,
490 })
491 }
492
493 fn read_material_list(&mut self) -> Result<RwMaterialList> {
494 self.file.read_section_header()?; self.file.read_section_header()?; let material_instance_count = self.file.get_stream().read_u32()?;
498 let mut material_indices = Vec::with_capacity(material_instance_count as usize);
499 for _ in 0..material_instance_count {
500 material_indices.push(self.file.get_stream().read_i32()?);
501 }
502
503 let mut material_data = Vec::with_capacity(material_instance_count as usize);
504 for i in 0..material_instance_count {
505 let material_index = material_indices[i as usize];
506 if material_index == -1 {
507 material_data.push(self.read_material()?);
508 } else {
509 material_data.push(material_data[material_index as usize].clone());
510 }
511 }
512
513 Ok(RwMaterialList {
514 material_instance_count,
515 material_data,
516 })
517 }
518
519 fn read_material(&mut self) -> Result<RwMaterial> {
520 self.file.read_section_header()?; let header = self.file.read_section_header()?; self.file.get_stream().skip(4)?; let color = RwColor {
526 r: self.file.get_stream().read_u8()?,
527 g: self.file.get_stream().read_u8()?,
528 b: self.file.get_stream().read_u8()?,
529 a: self.file.get_stream().read_u8()?,
530 };
531
532 self.file.get_stream().skip(4)?; let is_textured = self.file.get_stream().read_u32()? > 0;
535
536 let mut ambient = None;
537 let mut specular = None;
538 let mut diffuse = None;
539
540 if header.version_number > 0x30400 {
541 ambient = Some(self.file.get_stream().read_f32()?);
542 specular = Some(self.file.get_stream().read_f32()?);
543 diffuse = Some(self.file.get_stream().read_f32()?);
544 }
545
546 let mut texture = None;
547 if is_textured {
548 texture = Some(self.read_texture()?);
549 }
550
551 let size = self.file.read_section_header()?.section_size;
552 self.file.get_stream().skip(size as u64)?;
553
554 Ok(RwMaterial {
555 color,
556 is_textured,
557 ambient,
558 specular,
559 diffuse,
560 texture,
561 })
562 }
563
564 fn read_texture(&mut self) -> Result<RwTexture> {
565 self.file.read_section_header()?; self.file.read_section_header()?; let texture_data = self.file.get_stream().read_u32()?;
569 let texture_filtering = (texture_data & 0xFF) as u8;
570 let u_addressing = ((texture_data & 0xF00) >> 8) as u8;
571 let v_addressing = ((texture_data & 0xF000) >> 12) as u8;
572 let uses_mip_levels = (texture_data & (1 << 16)) != 0;
573
574 let texture_name_size = self.file.read_section_header()?.section_size;
575 let texture_name = self.file.get_stream().read_string(texture_name_size as usize)?;
576
577 let size1 = self.file.read_section_header()?.section_size;
578 self.file.get_stream().skip(size1 as u64)?;
579 let size2 = self.file.read_section_header()?.section_size;
580 self.file.get_stream().skip(size2 as u64)?;
581
582 Ok(RwTexture {
583 texture_filtering,
584 u_addressing,
585 v_addressing,
586 uses_mip_levels,
587 texture_name,
588 })
589 }
590
591 fn read_bin_mesh(&mut self) -> Result<RwBinMesh> {
592 self.file.read_section_header()?; self.file.get_stream().skip(4)?; let mesh_count = self.file.get_stream().read_u32()?;
596 self.file.get_stream().skip(4)?; let mut meshes = Vec::with_capacity(mesh_count as usize);
599 for _ in 0..mesh_count {
600 meshes.push(self.read_mesh()?);
601 }
602
603 Ok(RwBinMesh {
604 mesh_count,
605 meshes,
606 })
607 }
608
609 fn read_mesh(&mut self) -> Result<RwMesh> {
610 let index_count = self.file.get_stream().read_u32()?;
611 let material_index = self.file.get_stream().read_u32()?;
612
613 let mut indices = Vec::with_capacity(index_count as usize);
614 for _ in 0..index_count {
615 indices.push(self.file.get_stream().read_u32()?);
616 }
617
618 Ok(RwMesh {
619 index_count,
620 material_index,
621 indices,
622 })
623 }
624
625 fn read_skin(&mut self, vertex_count: u32) -> Result<RwSkin> {
626 let bone_count = self.file.get_stream().read_u8()?;
627 let used_bone_count = self.file.get_stream().read_u8()?;
628 let max_weights_per_vertex = self.file.get_stream().read_u8()?;
629
630 self.file.get_stream().skip(1)?; self.file.get_stream().skip(used_bone_count as u64)?; let mut bone_vertex_indices = Vec::with_capacity(vertex_count as usize);
634 for _ in 0..vertex_count {
635 let mut indices = Vec::with_capacity(4);
636 for _ in 0..4 {
637 indices.push(self.file.get_stream().read_u8()?);
638 }
639 bone_vertex_indices.push(indices);
640 }
641
642 let mut vertex_weights = Vec::with_capacity(vertex_count as usize);
643 for _ in 0..vertex_count {
644 let mut weights = Vec::with_capacity(4);
645 for _ in 0..4 {
646 weights.push(self.file.get_stream().read_f32()?);
647 }
648 vertex_weights.push(weights);
649 }
650
651 let mut inverse_bone_matrices = Vec::with_capacity(bone_count as usize);
652 for _ in 0..bone_count {
653 inverse_bone_matrices.push(RwMatrix4 {
654 right: RwVector4 {
655 x: self.file.get_stream().read_f32()?,
656 y: self.file.get_stream().read_f32()?,
657 z: self.file.get_stream().read_f32()?,
658 t: self.file.get_stream().read_f32()?,
659 },
660 up: RwVector4 {
661 x: self.file.get_stream().read_f32()?,
662 y: self.file.get_stream().read_f32()?,
663 z: self.file.get_stream().read_f32()?,
664 t: self.file.get_stream().read_f32()?,
665 },
666 at: RwVector4 {
667 x: self.file.get_stream().read_f32()?,
668 y: self.file.get_stream().read_f32()?,
669 z: self.file.get_stream().read_f32()?,
670 t: self.file.get_stream().read_f32()?,
671 },
672 transform: RwVector4 {
673 x: self.file.get_stream().read_f32()?,
674 y: self.file.get_stream().read_f32()?,
675 z: self.file.get_stream().read_f32()?,
676 t: self.file.get_stream().read_f32()?,
677 },
678 });
679 }
680
681 Ok(RwSkin {
682 bone_count,
683 used_bone_count,
684 max_weights_per_vertex,
685 bone_vertex_indices,
686 vertex_weights,
687 inverse_bone_matrices,
688 })
689 }
690
691 fn read_anim_node(&mut self) -> Result<RwAnimNode> {
692 self.file.get_stream().skip(4)?; let bone_id = self.file.get_stream().read_i32()?;
694 let bone_count = self.file.get_stream().read_i32()?;
695 let mut bones = Vec::with_capacity(bone_count as usize);
696
697 if bone_id == 0 {
698 self.file.get_stream().skip(8)?; }
700
701 if bone_count > 0 {
702 for _ in 0..bone_count {
703 bones.push(RwBone {
704 bone_id: self.file.get_stream().read_i32()?,
705 bone_index: self.file.get_stream().read_i32()?,
706 flags: self.file.get_stream().read_i32()?,
707 });
708 }
709 }
710
711 Ok(RwAnimNode {
712 bone_id,
713 bones_count: bone_count,
714 bones,
715 })
716 }
717}