diff --git a/Cargo.lock b/Cargo.lock index f858028..e2c66fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1438,6 +1438,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8ecd80612937e0267909d5351770fe150004e24dab93954f69ca62eecd3f77e" dependencies = [ "bytemuck", + "mint", ] [[package]] @@ -1733,6 +1734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" dependencies = [ "bytemuck", + "mint", "serde", ] @@ -2235,6 +2237,12 @@ dependencies = [ "adler", ] +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + [[package]] name = "mio" version = "0.8.6" @@ -2839,6 +2847,7 @@ dependencies = [ "image", "log", "memmap2", + "mint", "tegra_swizzle", "uuid", ] @@ -2874,6 +2883,7 @@ dependencies = [ "bevy", "bevy_egui", "bevy_embedded_assets", + "bevy_math", "bevy_mod_raycast", "binrw", "bit-set", @@ -2883,6 +2893,7 @@ dependencies = [ "half 3.0.0-dev", "image", "log", + "mint", "num-traits", "retrolib", "uuid", diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 0fdda29..332f098 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -20,5 +20,6 @@ flate2 = "1.0.25" image = "0.24.5" log = "0.4.17" memmap2 = "0.5.9" +mint = "0.5.9" tegra_swizzle = "0.3.1" uuid = "1.3.0" diff --git a/lib/src/format/mod.rs b/lib/src/format/mod.rs index c67b4e1..c6c227c 100644 --- a/lib/src/format/mod.rs +++ b/lib/src/format/mod.rs @@ -65,13 +65,78 @@ impl PartialEq<[u8; 4]> for FourCC { pub fn peek_four_cc(data: &[u8]) -> FourCC { FourCC(*array_ref!(data, 0, 4)) } #[binrw] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct CVector3f { pub x: f32, pub y: f32, pub z: f32, } +impl CVector3f { + #[inline] + pub fn new(x: f32, y: f32, z: f32) -> Self { Self { x, y, z } } + + #[inline] + pub fn splat(xyz: f32) -> Self { Self { x: xyz, y: xyz, z: xyz } } + + #[inline] + pub fn to_array(self) -> [f32; 3] { [self.x, self.y, self.z] } +} +impl From<[f32; 3]> for CVector3f { + fn from(value: [f32; 3]) -> Self { Self { x: value[0], y: value[1], z: value[2] } } +} +impl From for [f32; 3] { + fn from(value: CVector3f) -> Self { value.to_array() } +} + +impl From for mint::Vector3 { + fn from(value: CVector3f) -> Self { Self::from([value.x, value.y, value.z]) } +} +impl From> for CVector3f { + fn from(value: mint::Vector3) -> Self { Self { x: value.x, y: value.y, z: value.z } } +} +impl mint::IntoMint for CVector3f { + type MintType = mint::Vector3; +} + +#[binrw] +#[derive(Copy, Clone, Debug, Default)] +pub struct CVector4f { + pub x: f32, + pub y: f32, + pub z: f32, + pub w: f32, +} + +impl CVector4f { + #[inline] + pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self { Self { x, y, z, w } } + + #[inline] + pub fn splat(xyzw: f32) -> Self { Self { x: xyzw, y: xyzw, z: xyzw, w: xyzw } } + + #[inline] + pub fn to_array(self) -> [f32; 4] { [self.x, self.y, self.z, self.w] } +} +impl From<[f32; 4]> for CVector4f { + fn from(value: [f32; 4]) -> Self { Self { x: value[0], y: value[1], z: value[2], w: value[3] } } +} +impl From for [f32; 4] { + fn from(value: CVector4f) -> Self { value.to_array() } +} + +impl From for mint::Vector4 { + fn from(value: CVector4f) -> Self { Self::from([value.x, value.y, value.z, value.w]) } +} +impl From> for CVector4f { + fn from(value: mint::Vector4) -> Self { + Self { x: value.x, y: value.y, z: value.z, w: value.w } + } +} +impl mint::IntoMint for CVector4f { + type MintType = mint::Vector4; +} + #[binrw] #[derive(Copy, Clone, Debug)] pub struct CColor4f { @@ -81,19 +146,40 @@ pub struct CColor4f { pub a: f32, } +impl Default for CColor4f { + fn default() -> Self { Self { r: 0.0, g: 0.0, b: 0.0, a: 1.0 } } +} impl CColor4f { + #[inline] + pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self { Self { r, g, b, a } } + + #[inline] + pub fn splat(rgba: f32) -> Self { Self { r: rgba, g: rgba, b: rgba, a: rgba } } + #[inline] pub fn to_array(self) -> [f32; 4] { [self.r, self.g, self.b, self.a] } } +impl From<[f32; 4]> for CColor4f { + fn from(value: [f32; 4]) -> Self { Self { r: value[0], g: value[1], b: value[2], a: value[3] } } +} impl From for [f32; 4] { fn from(value: CColor4f) -> Self { value.to_array() } } -impl Default for CColor4f { - fn default() -> Self { Self { r: 0.0, g: 0.0, b: 0.0, a: 1.0 } } + +impl From for mint::Vector4 { + fn from(value: CColor4f) -> Self { Self::from([value.r, value.g, value.b, value.a]) } +} +impl From> for CColor4f { + fn from(value: mint::Vector4) -> Self { + Self { r: value.x, g: value.y, b: value.z, a: value.w } + } +} +impl mint::IntoMint for CColor4f { + type MintType = mint::Vector4; } #[binrw] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct CVector4i { pub x: i32, pub y: i32, @@ -102,50 +188,132 @@ pub struct CVector4i { } impl CVector4i { + #[inline] + pub fn new(x: i32, y: i32, z: i32, w: i32) -> Self { Self { x, y, z, w } } + + #[inline] + pub fn splat(xyzw: i32) -> Self { Self { x: xyzw, y: xyzw, z: xyzw, w: xyzw } } + #[inline] pub fn to_array(self) -> [i32; 4] { [self.x, self.y, self.z, self.w] } } +impl From<[i32; 4]> for CVector4i { + fn from(value: [i32; 4]) -> Self { Self { x: value[0], y: value[1], z: value[2], w: value[3] } } +} +impl From for [i32; 4] { + fn from(value: CVector4i) -> Self { value.to_array() } +} + +impl From for mint::Vector4 { + fn from(value: CVector4i) -> Self { Self::from([value.x, value.y, value.z, value.w]) } +} +impl From> for CVector4i { + fn from(value: mint::Vector4) -> Self { + Self { x: value.x, y: value.y, z: value.z, w: value.w } + } +} +impl mint::IntoMint for CVector4i { + type MintType = mint::Vector4; +} #[binrw] -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub struct CMatrix4f { pub m: [f32; 16], } +impl Default for CMatrix4f { + fn default() -> Self { + Self { + #[rustfmt::skip] + m: [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + ], + } + } +} +impl From for mint::RowMatrix4 { + fn from(value: CMatrix4f) -> Self { Self::from(value.m) } +} +impl From> for CMatrix4f { + fn from(value: mint::RowMatrix4) -> Self { Self { m: value.into() } } +} +impl mint::IntoMint for CMatrix4f { + type MintType = mint::RowMatrix4; +} + #[binrw] -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub struct CAABox { pub min: CVector3f, pub max: CVector3f, } -#[binrw] -#[derive(Clone, Debug)] -pub struct CTransform4f { - m00: f32, - m01: f32, - m02: f32, - m03: f32, - m10: f32, - m11: f32, - m12: f32, - m13: f32, - m20: f32, - m21: f32, - m22: f32, - m23: f32, +impl Default for CAABox { + fn default() -> Self { + Self { min: CVector3f::splat(f32::MAX), max: CVector3f::splat(f32::MIN) } + } } +#[binrw] +#[derive(Copy, Clone, Debug)] +pub struct CTransform4f { + m0: CVector4f, + m1: CVector4f, + m2: CVector4f, +} + +impl Default for CTransform4f { + fn default() -> Self { + Self { + m0: CVector4f::new(1.0, 0.0, 0.0, 0.0), + m1: CVector4f::new(0.0, 1.0, 0.0, 0.0), + m2: CVector4f::new(0.0, 0.0, 1.0, 0.0), + } + } +} impl CTransform4f { #[inline] - #[rustfmt::skip] - pub fn to_matrix_array(&self) -> [f32; 16] { - [ - self.m00, self.m10, self.m20, 0.0, - self.m01, self.m11, self.m21, 0.0, - self.m02, self.m12, self.m22, 0.0, - self.m03, self.m13, self.m23, 1.0, - ] + pub fn translation(&self) -> CVector3f { CVector3f::new(self.m0.w, self.m1.w, self.m2.w) } +} +impl From for mint::RowMatrix3x4 { + fn from(value: CTransform4f) -> Self { + Self::from([value.m0.into(), value.m1.into(), value.m2.into()]) + } +} +impl From> for CTransform4f { + fn from(value: mint::RowMatrix3x4) -> Self { + Self { m0: value.x.into(), m1: value.y.into(), m2: value.z.into() } + } +} +impl mint::IntoMint for CTransform4f { + type MintType = mint::RowMatrix3x4; +} + +impl From for mint::RowMatrix4 { + // noinspection DuplicatedCode + fn from(value: CTransform4f) -> Self { + Self::from([ + [value.m0.x, value.m0.y, value.m0.z, value.m0.w], + [value.m1.x, value.m1.y, value.m1.z, value.m1.w], + [value.m2.x, value.m2.y, value.m2.z, value.m2.w], + [0.0, 0.0, 0.0, 1.0], + ]) + } +} + +impl From for mint::ColumnMatrix4 { + // noinspection DuplicatedCode + fn from(value: CTransform4f) -> Self { + Self::from([ + [value.m0.x, value.m1.x, value.m2.x, 0.0], + [value.m0.y, value.m1.y, value.m2.y, 0.0], + [value.m0.z, value.m1.z, value.m2.z, 0.0], + [value.m0.w, value.m1.w, value.m2.w, 1.0], + ]) } } diff --git a/retrotool-gui/Cargo.toml b/retrotool-gui/Cargo.toml index be2c9fe..0156723 100644 --- a/retrotool-gui/Cargo.toml +++ b/retrotool-gui/Cargo.toml @@ -20,15 +20,17 @@ anyhow = "1.0.69" astc-decode = "0.3.1" bevy_egui = "0.20.1" bevy_embedded_assets = { version = "0.7.0", optional = true } +bevy_math = { version = "0.10.0", features = ["mint"] } bevy_mod_raycast = { git = "https://github.com/encounter/bevy_mod_raycast", branch = "updates" } binrw = "0.11.1" bit-set = "0.5.3" bytemuck = { version = "1.13.0", features = ["min_const_generics"] } -egui = "0.21.0" +egui = { version = "0.21.0", features = ["mint"] } egui_dock = "0.4.0" half = { git = "https://github.com/encounter/half-rs", branch = "inline", features = ["bytemuck"] } image = "0.24.5" log = "0.4.17" +mint = "0.5.9" num-traits = "0.2.15" retrolib = { path = "../lib" } uuid = "1.3.0" diff --git a/retrotool-gui/src/render/camera.rs b/retrotool-gui/src/render/camera.rs index de89a3d..cf915d5 100644 --- a/retrotool-gui/src/render/camera.rs +++ b/retrotool-gui/src/render/camera.rs @@ -35,8 +35,7 @@ impl ModelCamera { let mut pan = Vec2::ZERO; let scroll = { if response.hovered() { - // let delta = ui.input(|i| i.scroll_delta); - Vec2::new(scroll_delta.x, scroll_delta.y) + mint::Vector2::from(scroll_delta).into() } else { Vec2::ZERO } @@ -50,11 +49,9 @@ impl ModelCamera { self.upside_down = up.y <= 0.0; } if response.dragged_by(PointerButton::Primary) { - let delta = response.drag_delta(); - rotation_move = Vec2::new(delta.x, delta.y); + rotation_move = mint::Vector2::from(response.drag_delta()).into(); } else if response.dragged_by(PointerButton::Middle) { - let delta = response.drag_delta(); - pan = Vec2::new(delta.x, delta.y); + pan = mint::Vector2::from(response.drag_delta()).into(); } if rotation_move.length_squared() > 0.0 { any = true; @@ -75,7 +72,7 @@ impl ModelCamera { any = true; if let Projection::Perspective(projection) = &self.projection { pan *= Vec2::new(projection.fov * projection.aspect_ratio, projection.fov) - / Vec2::new(rect.width(), rect.height()); + / Vec2::from(mint::Vector2::from(rect.size())); } // translate by local axes let right = self.transform.rotation * Vec3::X * -pan.x; diff --git a/retrotool-gui/src/render/model.rs b/retrotool-gui/src/render/model.rs index 1ca8a1d..f17810d 100644 --- a/retrotool-gui/src/render/model.rs +++ b/retrotool-gui/src/render/model.rs @@ -88,10 +88,6 @@ pub fn load_model(asset: &ModelAsset, meshes: &mut Assets) -> Result) -> Result Aabb { - Aabb::from_min_max( - Vec3::new(aabb.min.x, aabb.min.y, aabb.min.z), - Vec3::new(aabb.max.x, aabb.max.y, aabb.max.z), - ) + let min = mint::Vector3::from(aabb.min); + let max = mint::Vector3::from(aabb.max); + Aabb::from_min_max(min.into(), max.into()) } +#[inline] pub fn convert_transform(xf: &CTransform4f) -> Transform { - Transform::from_matrix(Mat4::from_cols_array(&xf.to_matrix_array())) + let mtx = mint::ColumnMatrix4::from(*xf); + Transform::from_matrix(mtx.into()) } #[derive(Debug, Clone, Default)] diff --git a/retrotool-gui/src/tabs/modcon.rs b/retrotool-gui/src/tabs/modcon.rs index a4f7c8a..7bb5ca8 100644 --- a/retrotool-gui/src/tabs/modcon.rs +++ b/retrotool-gui/src/tabs/modcon.rs @@ -238,7 +238,8 @@ impl SystemTab for ModConTab { min = info.aabb.min().min(min); max = info.aabb.max().max(max); } - self.camera.init(&Aabb::from_min_max(min.into(), max.into()), true); + let aabb = Aabb::from_min_max(min.into(), max.into()); + self.camera.init(&aabb, true); } // FIXME diff --git a/retrotool-gui/src/tabs/texture.rs b/retrotool-gui/src/tabs/texture.rs index dd37760..b228710 100644 --- a/retrotool-gui/src/tabs/texture.rs +++ b/retrotool-gui/src/tabs/texture.rs @@ -154,21 +154,17 @@ impl SystemTab for TextureTab { mip.texture_ids.len(), )); } - let w = mip.width; - let h = mip.height; - let size = egui::Vec2 { x: w as f32, y: h as f32 }; + let size = egui::Vec2::new(mip.width as f32, mip.height as f32); let draw_image = |ui: &mut egui::Ui, rect: &egui::Rect, i: usize, x: u32, y: u32, flip: bool| { - let min = egui::Vec2 { x: (w * x) as f32, y: (h * y) as f32 }; - let max = egui::Vec2 { x: (w * (x + 1)) as f32, y: (h * (y + 1)) as f32 }; + let min = rect.min + size * egui::Vec2::new(x as f32, y as f32); let y_range = if flip { 1.0..=0.0 } else { 0.0..=1.0 }; egui::widgets::Image::new(mip.texture_ids[i], size) .uv(egui::Rect::from_x_y_ranges(0.0..=1.0, y_range)) - .paint_at(ui, egui::Rect { min: rect.min + min, max: rect.min + max }); + .paint_at(ui, egui::Rect::from_min_size(min, size)); }; if txtr.inner.head.kind == ETextureType::Cube && mip.texture_ids.len() == 6 { - let (_, rect) = - ui.allocate_space(egui::Vec2 { x: (w * 4) as f32, y: (h * 3) as f32 }); + let (_, rect) = ui.allocate_space(size * egui::Vec2::new(4.0, 3.0)); draw_image(ui, &rect, 2, 1, 0, self.v_flip); draw_image(ui, &rect, 1, 0, 1, self.v_flip); draw_image(ui, &rect, 4, 1, 1, self.v_flip); @@ -176,10 +172,8 @@ impl SystemTab for TextureTab { draw_image(ui, &rect, 5, 3, 1, self.v_flip); draw_image(ui, &rect, 3, 1, 2, self.v_flip); } else { - let (_, rect) = ui.allocate_space(egui::Vec2 { - x: (w as usize * mip.texture_ids.len()) as f32, - y: h as f32, - }); + let (_, rect) = + ui.allocate_space(size * egui::Vec2::new(mip.texture_ids.len() as f32, 1.0)); for i in 0..mip.texture_ids.len() { draw_image(ui, &rect, i, i as u32, 0, self.v_flip); }