use crate::Matrix3x3;
use crate::SsbhArray;
use crate::SsbhByteBuffer;
use crate::SsbhString;
use crate::Vector3;
use crate::Version;
use binrw::BinRead;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use ssbh_write::SsbhWrite;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq)]
#[br(import(major_version: u16, minor_version: u16))]
#[ssbhwrite(pad_after = 16, align_after = 8)]
pub enum Mesh {
#[br(pre_assert(major_version == 1 && minor_version == 8))]
V8(MeshInner<AttributeV8, SsbhArray<VertexWeightV8>>),
#[br(pre_assert(major_version == 1 && minor_version == 9))]
V9(MeshInner<AttributeV9, SsbhArray<VertexWeightV8>>),
#[br(pre_assert(major_version == 1 && minor_version == 10))]
V10(MeshInner<AttributeV10, SsbhByteBuffer>),
}
impl Version for Mesh {
fn major_minor_version(&self) -> (u16, u16) {
match self {
Mesh::V8(_) => (1, 8),
Mesh::V9(_) => (1, 9),
Mesh::V10(_) => (1, 10),
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq)]
pub struct MeshInner<
A: for<'a> BinRead<Args<'a> = ()> + SsbhWrite,
W1: for<'a> BinRead<Args<'a> = ()> + SsbhWrite,
> {
pub model_name: SsbhString,
pub bounding_info: BoundingInfo,
pub unk1: u32, pub objects: SsbhArray<MeshObject<A>>,
pub buffer_sizes: SsbhArray<u32>,
pub polygon_index_size: u64,
pub vertex_buffers: SsbhArray<SsbhByteBuffer>,
pub index_buffer: SsbhByteBuffer,
pub rigging_buffers: SsbhArray<RiggingGroup<W1>>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq, Eq)]
pub struct AttributeV8 {
pub usage: AttributeUsageV8,
pub data_type: AttributeDataTypeV8,
pub buffer_index: u32,
pub buffer_offset: u32,
pub subindex: u32,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq, Eq)]
pub struct AttributeV9 {
pub usage: AttributeUsageV9,
pub data_type: AttributeDataTypeV8,
pub buffer_index: u32,
pub buffer_offset: u32,
pub subindex: u64,
pub name: SsbhString,
pub attribute_names: SsbhArray<SsbhString>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq, Eq)]
pub struct AttributeV10 {
pub usage: AttributeUsageV9,
pub data_type: AttributeDataTypeV10,
pub buffer_index: u32,
pub buffer_offset: u32,
pub subindex: u64,
pub name: SsbhString,
pub attribute_names: SsbhArray<SsbhString>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, Default, PartialEq)]
pub struct BoundingInfo {
pub bounding_sphere: BoundingSphere,
pub bounding_volume: BoundingVolume,
pub oriented_bounding_box: OrientedBoundingBox,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, PartialEq, Default)]
pub struct BoundingSphere {
pub center: Vector3,
pub radius: f32,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, Default, PartialEq)]
pub struct BoundingVolume {
pub min: Vector3,
pub max: Vector3,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, Default, PartialEq)]
pub struct OrientedBoundingBox {
pub center: Vector3,
pub transform: Matrix3x3,
pub size: Vector3,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Copy, Clone, PartialEq, Eq)]
#[ssbhwrite(pad_after = 6)]
pub struct RiggingFlags {
pub max_influences: u8,
#[br(pad_after = 6)]
pub unk1: u8,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq)]
pub struct BoneBuffer<W2: for<'a> BinRead<Args<'a> = ()> + SsbhWrite> {
pub bone_name: SsbhString,
pub data: W2,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq)]
pub struct RiggingGroup<W3: for<'a> BinRead<Args<'a> = ()> + SsbhWrite> {
pub mesh_object_name: SsbhString,
pub mesh_object_subindex: u64,
pub flags: RiggingFlags,
pub buffers: SsbhArray<BoneBuffer<W3>>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite)]
#[br(import(major_version: u16, minor_version: u16))]
pub enum Attributes {
#[br(pre_assert(major_version == 1 && minor_version == 8))]
V8(SsbhArray<AttributeV8>),
#[br(pre_assert(major_version == 1 && minor_version == 9))]
V9(SsbhArray<AttributeV9>),
#[br(pre_assert(major_version == 1 && minor_version == 10))]
V10(SsbhArray<AttributeV10>),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq)]
pub struct VertexWeightV8 {
pub vertex_index: u32,
pub vertex_weight: f32,
}
#[derive(BinRead, Debug, Clone, PartialEq)]
pub struct VertexWeightV10 {
pub vertex_index: u16,
pub vertex_weight: f32,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq)]
pub struct MeshObject<A: for<'a> BinRead<Args<'a> = ()> + SsbhWrite> {
pub name: SsbhString,
pub subindex: u64,
pub parent_bone_name: SsbhString,
pub vertex_count: u32,
pub vertex_index_count: u32,
pub unk2: u32, pub vertex_buffer0_offset: u32,
pub vertex_buffer1_offset: u32,
pub vertex_buffer2_offset: u32,
pub vertex_buffer3_offset: u32,
pub stride0: u32,
pub stride1: u32,
pub stride2: u32,
pub stride3: u32,
pub index_buffer_offset: u32,
pub unk8: u32, pub draw_element_type: DrawElementType,
pub use_vertex_skinning: u32,
pub sort_bias: i32, pub depth_flags: DepthFlags,
pub bounding_info: BoundingInfo,
pub attributes: SsbhArray<A>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, PartialEq, Eq)]
#[ssbhwrite(pad_after = 2)]
pub struct DepthFlags {
pub disable_depth_write: u8,
#[br(pad_after = 2)]
pub disable_depth_test: u8,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, PartialEq, Eq)]
#[br(repr(u32))]
#[ssbhwrite(repr(u32))]
pub enum DrawElementType {
UnsignedShort = 0,
UnsignedInt = 1,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, PartialEq, Eq)]
#[br(repr(u32))]
#[ssbhwrite(repr(u32))]
pub enum AttributeDataTypeV10 {
Float3 = 0,
Byte4 = 2,
Float4 = 4,
HalfFloat4 = 5,
Float2 = 7,
HalfFloat2 = 8,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, PartialEq, Eq)]
#[br(repr(u32))]
#[ssbhwrite(repr(u32))]
pub enum AttributeDataTypeV8 {
Float3 = 820,
Float4 = 1076,
HalfFloat4 = 1077,
Float2 = 1079,
Byte4 = 1024,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, PartialEq, Eq)]
#[br(repr(u32))]
#[ssbhwrite(repr(u32))]
pub enum AttributeUsageV9 {
Position = 0,
Normal = 1,
Binormal = 2,
Tangent = 3,
TextureCoordinate = 4,
ColorSet = 5,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, SsbhWrite, Clone, Copy, PartialEq, Eq)]
#[br(repr(u32))]
#[ssbhwrite(repr(u32))]
pub enum AttributeUsageV8 {
Position = 0,
Normal = 1,
Tangent = 3,
TextureCoordinate = 4,
ColorSet = 8,
}