From fa4754aa7277cf4e94c5e43c2721c960afb90604 Mon Sep 17 00:00:00 2001 From: Dave Corley Date: Mon, 26 Feb 2024 21:56:40 -0600 Subject: [PATCH] Feat(main): Implement object rotation --- resources/Morrowind.fgd | 1 + src/main.rs | 19 +++++++++++-------- src/mesh.rs | 17 ++++++++++++++++- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/resources/Morrowind.fgd b/resources/Morrowind.fgd index 22574a8..007e5d7 100644 --- a/resources/Morrowind.fgd +++ b/resources/Morrowind.fgd @@ -16,6 +16,7 @@ Icon(string) : "Ingame icon used by the object. Visible within TrenchBroom. Be sure to include the relative path to the icon." : "tx_goldicon.tga" Value(int) : "Gold Value of the object ingame" : 420 Weight(float): "Weight of the object in Todd units." : "0.0" + Mangle(string): "Object rotation, not meant to be adjusted in the property view" ] @BaseClass base(Referenceable) = Wearable : "Wearable" diff --git a/src/main.rs b/src/main.rs index 60fc85d..bb6fec4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -209,6 +209,10 @@ fn main() { let mut mesh_distance: SV3 = find_geometric_center(&mesh.node_distances) * 2.0; mesh.final_distance = mesh_distance; + mesh.mangle = match get_prop("mangle", &prop_map) { + s if s.is_empty() => *get_rotation(&"0 0 0".to_string()), + mangle => *get_rotation(&mangle), + }; // Also use linked groups to determine if the mesh & base def should be ignored // Also we should probably just not check this way *only* and @@ -224,6 +228,7 @@ fn main() { mast_index: 0 as u32, refr_index: indices, translation: [mesh_distance.x, mesh_distance.y, mesh_distance.z], + rotation: [-mesh.mangle[0], -mesh.mangle[1], -mesh.mangle[2]], ..Default::default() }; @@ -245,17 +250,15 @@ fn main() { println!("Wrote {plugin_name} to disk successfully."); } -fn split_string_into_array(color_str: &String, alpha_str: &String) -> [u8; 4] { - let mut array = [0; 4]; - let colors: Vec<&str> = color_str.split_whitespace().collect(); +fn get_rotation(str: &String) -> Box<[f32; 3]> { + let rot: Vec<&str> = str.split_whitespace().collect(); + let mut array = [0.0f32; 3]; - for (index, color) in colors.iter().enumerate() { - array[index] = color.parse::().unwrap_or_default(); + for (index, axis) in rot.iter().enumerate() { + array[index] = axis.parse::().unwrap_or_default().to_radians(); } - array[3] = alpha_str.parse::().unwrap_or_default(); - - array + Box::new([array[2], array[0], array[1]]) } fn find_geometric_center(vertices: &Vec) -> SV3 { diff --git a/src/mesh.rs b/src/mesh.rs index f63f08c..28638ee 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,3 +1,4 @@ +use nalgebra::{Rotation3, Vector3}; use openmw_cfg::{find_file, get_config}; use shambler::{brush::BrushId, Vector3 as SV3}; use tes3::{ @@ -14,6 +15,7 @@ pub struct Mesh { pub stream: NiStream, pub base_index: NiLink, pub final_distance: SV3, + pub mangle: [f32; 3], collision_index: NiLink, root_index: NiLink, } @@ -40,6 +42,7 @@ impl Mesh { game_object: esp::TES3Object::Static(esp::Static::default()), node_distances: Vec::new(), final_distance: SV3::default(), + mangle: [0.0, 0.0, 0.0], } } @@ -58,12 +61,20 @@ impl Mesh { pub fn align_to_center(&mut self) { let center = Mesh::find_geometric_center(&self.node_distances); + let rotation = Rotation3::new(Vector3::new( + -self.mangle[0], + -self.mangle[1], + -self.mangle[2], + )); for tri_shape in self.stream.objects_of_type_mut::() { for vert in &mut tri_shape.vertices { vert.x -= center.x; vert.y -= center.y; vert.z -= center.z; - println!("{0:?}", vert); + let rotated_vert = rotation.transform_vector(&Vector3::new(vert.x, vert.y, vert.z)); + vert.x = rotated_vert[0]; + vert.y = rotated_vert[1]; + vert.z = rotated_vert[2]; } } @@ -71,6 +82,10 @@ impl Mesh { vert.x -= center.x; vert.y -= center.y; vert.z -= center.z; + let rotated_vert = rotation.transform_vector(&Vector3::new(vert.x, vert.y, vert.z)); + vert.x = rotated_vert[0]; + vert.y = rotated_vert[1]; + vert.z = rotated_vert[2]; } }