1use crate::{
51 parse_count16_offset32, parse_count32_offset32, parse_offset32_count32, parse_opt_ptr32,
52 parse_ptr32, xc3_write_binwrite_impl,
53};
54use bilge::prelude::*;
55use binrw::{args, binread, BinRead, BinWrite};
56use xc3_write::{Xc3Write, Xc3WriteOffsets};
57
58#[binread]
60#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
61#[derive(Debug, Xc3Write, PartialEq, Clone)]
62#[br(stream = r)]
63#[xc3(base_offset)]
64pub struct VertexData {
65 #[br(temp, try_calc = r.stream_position())]
66 base_offset: u64,
67
68 #[br(parse_with = parse_offset32_count32)]
70 #[br(args { offset: base_offset, inner: base_offset })]
71 #[xc3(offset_count(u32, u32))]
72 pub vertex_buffers: Vec<VertexBufferDescriptor>,
73
74 #[br(parse_with = parse_offset32_count32, offset = base_offset)]
75 #[xc3(offset_count(u32, u32))]
76 pub index_buffers: Vec<IndexBufferDescriptor>,
77
78 pub unk0: u32,
80 pub unk1: u32,
81 pub unk2: u32,
82
83 #[br(parse_with = parse_ptr32)]
84 #[br(args { offset: base_offset, inner: args! { count: buffer_info_count(&vertex_buffers) }})]
85 #[xc3(offset(u32))]
86 pub vertex_buffer_info: Vec<VertexBufferExtInfo>,
87
88 #[br(parse_with = parse_offset32_count32, offset = base_offset)]
90 #[xc3(offset_count(u32, u32))]
91 pub outline_buffers: Vec<OutlineBufferDescriptor>,
92
93 #[br(parse_with = parse_opt_ptr32)]
94 #[br(args { offset: base_offset, inner: base_offset })]
95 #[xc3(offset(u32))]
96 pub vertex_morphs: Option<VertexMorphs>,
97
98 #[br(parse_with = parse_count32_offset32, offset = base_offset)]
106 #[xc3(count_offset(u32, u32), align(4096))]
107 pub buffer: Vec<u8>,
108
109 #[br(parse_with = parse_opt_ptr32, offset = base_offset)]
111 #[xc3(offset(u32))]
112 pub unk_data: Option<UnkData>,
113
114 #[br(parse_with = parse_opt_ptr32)]
115 #[br(args { offset: base_offset, inner: base_offset })]
116 #[xc3(offset(u32))]
117 pub weights: Option<Weights>,
118
119 #[br(parse_with = parse_opt_ptr32, offset = base_offset)]
120 #[xc3(offset(u32))]
121 pub unk7: Option<Unk>,
122
123 pub unks: [u32; 5],
125}
126
127#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
128#[derive(Debug, BinRead, Xc3Write, PartialEq, Eq, Clone)]
129#[br(import_raw(base_offset: u64))]
130pub struct VertexBufferDescriptor {
131 pub data_offset: u32,
133 pub vertex_count: u32,
134 pub vertex_size: u32,
136
137 #[br(parse_with = parse_offset32_count32, offset = base_offset)]
139 #[xc3(offset_count(u32, u32))]
140 pub attributes: Vec<VertexAttribute>,
141
142 pub unk1: u32,
143 pub unk2: u32,
144 pub unk3: u32,
145}
146
147#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
152#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Eq, Clone, Copy)]
153pub struct VertexAttribute {
154 pub data_type: DataType,
155 pub data_size: u16,
157}
158
159#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
163#[derive(Debug, BinRead, BinWrite, PartialEq, Eq, Clone, Copy)]
164#[brw(repr(u16))]
165pub enum DataType {
166 Position = 0,
168 SkinWeights2 = 1,
172 BoneIndices2 = 2,
175 WeightIndex = 3,
180 WeightIndex2 = 4,
184 TexCoord0 = 5,
186 TexCoord1 = 6,
188 TexCoord2 = 7,
190 TexCoord3 = 8,
192 TexCoord4 = 9,
194 TexCoord5 = 10,
196 TexCoord6 = 11,
198 TexCoord7 = 12,
200 TexCoord8 = 13,
202 Blend = 14,
204 Unk15 = 15,
206 Unk16 = 16, VertexColor = 17,
209 Unk18 = 18,
211 Unk24 = 24,
213 Unk25 = 25,
215 Unk26 = 26,
217 Normal = 28,
219 Tangent = 29,
221 Unk30 = 30,
223 Unk31 = 31, Normal2 = 32,
226 ValInf = 33,
229 Normal3 = 34,
231 VertexColor3 = 35,
233 Position2 = 36,
235 Normal4 = 37,
239 OldPosition = 39,
241 Tangent2 = 40,
245 SkinWeights = 41,
247 BoneIndices = 42,
249 Flow = 52,
251}
252
253#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
255#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Eq, Clone)]
256pub struct IndexBufferDescriptor {
257 pub data_offset: u32,
259 pub index_count: u32,
260 pub primitive_type: PrimitiveType,
261 pub index_format: IndexFormat,
262 pub unk3: u32,
264 pub unk4: u32,
265}
266
267#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
268#[derive(Debug, BinRead, BinWrite, PartialEq, Eq, Clone, Copy)]
269#[brw(repr(u16))]
270pub enum PrimitiveType {
271 TriangleList = 0,
272 QuadList = 1,
273 TriangleStrip = 2,
274 TriangleListAdjacency = 3,
276}
277
278#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
279#[derive(Debug, BinRead, BinWrite, PartialEq, Eq, Clone, Copy)]
280#[brw(repr(u16))]
281pub enum IndexFormat {
282 Uint16 = 0,
283 Uint32 = 1,
284}
285
286#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
288#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
289#[br(import_raw(base_offset: u64))]
290pub struct VertexMorphs {
291 #[br(parse_with = parse_count32_offset32)]
292 #[br(args { offset: base_offset, inner: base_offset })]
293 #[xc3(count_offset(u32, u32))]
294 pub descriptors: Vec<MorphDescriptor>,
295
296 #[br(parse_with = parse_count32_offset32, offset = base_offset)]
297 #[xc3(count_offset(u32, u32))]
298 pub targets: Vec<MorphTarget>,
299
300 pub unks: [u32; 4],
302}
303
304#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
310#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
311#[br(import_raw(base_offset: u64))]
312pub struct MorphDescriptor {
313 pub vertex_buffer_index: u32,
314 pub target_start_index: u32,
315
316 #[br(parse_with = parse_count32_offset32, offset = base_offset)]
318 #[xc3(count_offset(u32, u32))]
319 pub param_indices: Vec<u16>,
320
321 pub unk2: u32, }
326
327#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
330#[derive(Debug, BinRead, BinWrite, PartialEq, Clone)]
331pub struct MorphTarget {
332 pub data_offset: u32,
334 pub vertex_count: u32,
335 pub vertex_size: u32,
336
337 pub flags: MorphTargetFlags,
338}
339
340#[bitsize(32)]
341#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
342#[derive(DebugBits, FromBits, BinRead, BinWrite, Clone, Copy, PartialEq)]
343#[br(map = u32::into)]
344#[bw(map = |&x| u32::from(x))]
345pub struct MorphTargetFlags {
346 pub unk1: u16, pub blend_target_buffer: bool,
349 pub default_buffer: bool,
351 pub param_buffer: bool,
353 pub unk5: u13, }
355
356#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
359#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
360#[br(import_raw(base_offset: u64))]
361pub struct Weights {
362 #[br(parse_with = parse_count32_offset32, offset = base_offset)]
364 #[xc3(count_offset(u32, u32))]
365 pub groups: Vec<WeightGroup>,
366
367 pub vertex_buffer_index: u16,
370
371 #[br(parse_with = parse_count16_offset32, offset = base_offset)]
373 #[xc3(count_offset(u16, u32))]
374 pub weight_lods: Vec<WeightLod>,
375
376 pub unk4: u32, pub unks: [u32; 4],
381}
382
383#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
391#[derive(Debug, PartialEq, Clone, BinRead, Xc3Write, Xc3WriteOffsets)]
392pub struct WeightGroup {
393 pub output_start_index: u32,
396 pub input_start_index: u32,
398 pub count: u32,
400 pub unks: [u32; 4], pub lod_group_index: u8,
404 pub lod_index: u8,
407 pub max_influences: u8,
410 pub unk4: u8,
411 pub unks2: [u32; 2],
412}
413
414#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
419#[derive(Debug, PartialEq, Clone, BinRead, Xc3Write, Xc3WriteOffsets)]
420pub struct WeightLod {
421 pub group_indices_plus_one: [u16; 9],
428}
429
430#[binread]
431#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
432#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
433#[br(stream = r)]
434#[xc3(base_offset)]
435pub struct Unk {
436 #[br(temp, try_calc = r.stream_position())]
437 base_offset: u64,
438
439 #[br(parse_with = parse_count32_offset32, offset = base_offset)]
440 #[xc3(count_offset(u32, u32))]
441 pub buffers: Vec<UnkBufferDescriptor>,
442
443 pub data_length: u32,
445
446 pub data_offset: u32,
448
449 pub unks: [u32; 8],
451}
452
453#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
454#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
455pub struct UnkBufferDescriptor {
456 pub unk1: u16,
457 pub unk2: u16, pub count: u32,
459 pub offset: u32,
460 pub unk5: u32,
461 pub start_index: u32,
462}
463
464#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
466#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
467pub struct VertexBufferExtInfo {
468 pub flags: VertexBufferExtInfoFlags,
469 pub outline_buffer_index: u16,
471 pub morph_target_start_index: u16,
474 pub morph_target_count: u16,
478 pub unk: u32,
480}
481
482#[bitsize(16)]
483#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
484#[derive(DebugBits, FromBits, BinRead, BinWrite, Clone, Copy, PartialEq)]
485#[br(map = u16::into)]
486#[bw(map = |&x| u16::from(x))]
487pub struct VertexBufferExtInfoFlags {
488 pub has_outline_buffer: bool,
489 pub has_morph_targets: bool,
490 pub unk: u14,
491}
492
493#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
494#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
495pub struct OutlineBufferDescriptor {
496 pub data_offset: u32,
498 pub vertex_count: u32,
499 pub vertex_size: u32,
501 pub unk: u32,
503}
504
505#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
506#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
507pub struct UnkData {
508 pub unk1: u32, pub vertex_data_offset: u32,
510 pub vertex_data_length: u32,
511 pub uniform_data_offset: u32,
512 pub uniform_data_length: u32,
513 pub vertex_count: u32,
514 pub vertex_size: u32,
515 pub unk: [f32; 6],
517}
518
519impl DataType {
520 pub fn size_in_bytes(&self) -> usize {
521 match self {
522 DataType::Position => 12,
523 DataType::SkinWeights2 => 12,
524 DataType::BoneIndices2 => 4,
525 DataType::WeightIndex => 4,
526 DataType::WeightIndex2 => 4,
527 DataType::TexCoord0 => 8,
528 DataType::TexCoord1 => 8,
529 DataType::TexCoord2 => 8,
530 DataType::TexCoord3 => 8,
531 DataType::TexCoord4 => 8,
532 DataType::TexCoord5 => 8,
533 DataType::TexCoord6 => 8,
534 DataType::TexCoord7 => 8,
535 DataType::TexCoord8 => 8,
536 DataType::Blend => 4,
537 DataType::Unk15 => 12,
538 DataType::Unk16 => 8,
539 DataType::VertexColor => 4,
540 DataType::Unk18 => 12,
541 DataType::Unk24 => 16,
542 DataType::Unk25 => 16,
543 DataType::Unk26 => 16,
544 DataType::Normal => 4,
545 DataType::Tangent => 4,
546 DataType::Unk30 => 4, DataType::Unk31 => 4,
548 DataType::Normal2 => 4,
549 DataType::ValInf => 4,
550 DataType::Normal3 => 4,
551 DataType::VertexColor3 => 4,
552 DataType::Position2 => 12,
553 DataType::Normal4 => 4,
554 DataType::OldPosition => 12,
555 DataType::Tangent2 => 4,
556 DataType::SkinWeights => 8,
557 DataType::BoneIndices => 4,
558 DataType::Flow => 2,
559 }
560 }
561}
562
563impl From<DataType> for VertexAttribute {
564 fn from(data_type: DataType) -> Self {
565 Self {
566 data_type,
567 data_size: data_type.size_in_bytes() as u16,
568 }
569 }
570}
571
572xc3_write_binwrite_impl!(
573 DataType,
574 PrimitiveType,
575 IndexFormat,
576 MorphTarget,
577 VertexBufferExtInfoFlags
578);
579
580fn buffer_info_count(vertex_buffers: &[VertexBufferDescriptor]) -> usize {
581 vertex_buffers
583 .iter()
584 .filter(|b| {
585 !b.attributes
586 .iter()
587 .any(|a| a.data_type == DataType::SkinWeights)
588 })
589 .count()
590}
591
592impl Xc3WriteOffsets for VertexDataOffsets<'_> {
593 type Args = ();
594
595 fn write_offsets<W: std::io::Write + std::io::Seek>(
596 &self,
597 writer: &mut W,
598 _base_offset: u64,
599 data_ptr: &mut u64,
600 endian: xc3_write::Endian,
601 _args: Self::Args,
602 ) -> xc3_write::Xc3Result<()> {
603 let base_offset = self.base_offset;
604
605 let vertex_buffers = self
606 .vertex_buffers
607 .write(writer, base_offset, data_ptr, endian)?;
608 self.index_buffers
609 .write(writer, base_offset, data_ptr, endian)?;
610 self.vertex_buffer_info
611 .write(writer, base_offset, data_ptr, endian)?;
612
613 if !self.outline_buffers.data.is_empty() {
615 self.outline_buffers
616 .write(writer, base_offset, data_ptr, endian)?;
617 }
618
619 for vertex_buffer in vertex_buffers.0 {
623 vertex_buffer
624 .attributes
625 .write(writer, base_offset, data_ptr, endian)?;
626 }
627
628 self.weights
629 .write_full(writer, base_offset, data_ptr, endian, ())?;
630
631 self.unk_data.write(writer, base_offset, data_ptr, endian)?;
632
633 if let Some(vertex_animation) =
634 self.vertex_morphs
635 .write(writer, base_offset, data_ptr, endian)?
636 {
637 let descriptors =
638 vertex_animation
639 .descriptors
640 .write(writer, base_offset, data_ptr, endian)?;
641 vertex_animation
642 .targets
643 .write(writer, base_offset, data_ptr, endian)?;
644
645 for descriptor in descriptors.0 {
646 descriptor
647 .param_indices
648 .write(writer, base_offset, data_ptr, endian)?;
649 }
650 }
651
652 self.unk7
653 .write_full(writer, base_offset, data_ptr, endian, ())?;
654
655 self.buffer.write(writer, base_offset, data_ptr, endian)?;
656
657 Ok(())
658 }
659}