From d73f6fda21286fee5829c149d0b7f6e1674c4b75 Mon Sep 17 00:00:00 2001 From: Theis Pieter Hollebeek Date: Tue, 7 Apr 2026 14:45:14 +0200 Subject: [PATCH] dump quaternion trash --- simul/src/m3x3.rs | 4 ++++ simul/src/main.rs | 7 +++--- simul/src/quats.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++ simul/src/scene.rs | 9 ++++++++ simul/src/tri3.rs | 5 ++++- simul/src/v3.rs | 19 +++++++++++++++- 6 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 simul/src/quats.rs diff --git a/simul/src/m3x3.rs b/simul/src/m3x3.rs index 3c85fe1..d6150d3 100644 --- a/simul/src/m3x3.rs +++ b/simul/src/m3x3.rs @@ -13,6 +13,10 @@ impl M3x3 { Self([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) } + pub fn new(v: [[f64; 3]; 3]) -> Self { + Self(v) + } + pub fn from_v3_rot(rot: V3) -> Self { M3x3::new_rotate_x(rot.0) * M3x3::new_rotate_y(rot.1) * M3x3::new_rotate_z(rot.2) } diff --git a/simul/src/main.rs b/simul/src/main.rs index 2b0cc23..44a4b6a 100644 --- a/simul/src/main.rs +++ b/simul/src/main.rs @@ -6,6 +6,7 @@ use std::{collections::HashMap, f64::consts::PI, fs::File, io::BufReader}; use crate::{ m3x3::M3x3, + quats::RadianQuat, scene::{Model, Scene}, tri2::Tri2, tri3::Tri3, @@ -15,6 +16,7 @@ use crate::{ }; mod m3x3; +mod quats; mod scene; mod tri2; mod tri3; @@ -75,8 +77,7 @@ fn calculate_accel_axis_angle(axis: f64, tangent0: f64, tangent1: f64) -> f64 { impl window::App for App { fn update(&mut self, delta_time: std::time::Duration) { - self.rot.0 += PI * 2.0 * delta_time.as_secs_f64() * 0.2; - self.rot.1 += PI * 2.0 * delta_time.as_secs_f64() * 0.2; + self.rot.0 += PI * 2.0 * delta_time.as_secs_f64() * 0.05; // self.rot.2 += PI * 2.0 * delta_time.as_secs_f64() * 0.2; self.motion_dev @@ -104,7 +105,7 @@ impl window::App for App { let mut cube = Model::new(); let cube_obj = self.assets.get("assets/cube.obj").unwrap(); cube.add_obj(&cube_obj, Color::RGB(165, 125, 165)) - .rotate_by_m3x3(M3x3::from_v3_rot(self.rot)) + .rotate_by_m3x3(self.dev_rot_rot) .scale(V3(0.4, 0.4, 0.4)) .translate(V3(0.0, 0.0, 1.0)); scene.draw_model(cube); diff --git a/simul/src/quats.rs b/simul/src/quats.rs new file mode 100644 index 0000000..4ddf968 --- /dev/null +++ b/simul/src/quats.rs @@ -0,0 +1,54 @@ +use crate::v3::V3; + +const I: V3 = V3(1.0, 0.0, 0.0); +const J: V3 = V3(0.0, 1.0, 0.0); +const K: V3 = V3(0.0, 0.0, 1.0); + +#[derive(Copy, Clone)] +pub struct RadianQuat { + pub rad: f64, + pub u: V3, +} + +#[derive(Copy, Clone)] +pub struct Quat { + pub a: f64, + pub u: V3, +} + +impl Quat { + fn len(&self) -> f64 { + (self.a.powi(2) + self.u.0.powi(2) + self.u.1.powi(2) + self.u.2.powi(2)).sqrt() + } + fn as_unit(&self) -> Quat { + let len = self.len(); + Quat { + a: self.a / len, + u: self.u.map(|x| x / len), + } + } +} + +impl RadianQuat { + pub fn as_quat(&self) -> Quat { + let RadianQuat { rad, u } = self.as_unit(); + Quat { + a: rad.cos(), + u: u.map(|x| x * rad.sin()), + } + } + fn as_unit(&self) -> Self { + let len = self.u.0 + self.u.1 + self.u.2; + let u = self.u.map(|x| x / len); + + RadianQuat { rad: self.rad, u } + } + pub fn as_inverse_quat(&self) -> Quat { + let RadianQuat { rad, u } = self.as_unit(); + let u = u.map(|x| x * -1.0 * rad.sin()); + Quat { a: -rad.cos(), u } + } + pub fn vector_quat(&self) -> V3 { + self.u + } +} diff --git a/simul/src/scene.rs b/simul/src/scene.rs index 811cf77..65dfa3c 100644 --- a/simul/src/scene.rs +++ b/simul/src/scene.rs @@ -4,6 +4,7 @@ use obj::Obj; use crate::{ m3x3::M3x3, + quats::RadianQuat, tri2::Tri2, tri3::Tri3, v3::V3, @@ -108,6 +109,14 @@ impl Model { self } + pub fn rotate_by_quat(&mut self, rot: RadianQuat) -> &mut Self { + for tri in &mut self.tris { + tri.0 = tri.0.rotate_by_quat(rot); + tri.1 = tri.1.rotate_by_quat(rot); + } + self + } + pub fn scale(&mut self, scale: V3) -> &mut Self { for tri in &mut self.tris { tri.0 = tri.0.scale(scale); diff --git a/simul/src/tri3.rs b/simul/src/tri3.rs index 4e2d4c5..0a88cf8 100644 --- a/simul/src/tri3.rs +++ b/simul/src/tri3.rs @@ -1,4 +1,4 @@ -use crate::{m3x3::M3x3, tri2::Tri2, v3::V3}; +use crate::{m3x3::M3x3, quats::RadianQuat, tri2::Tri2, v3::V3}; #[derive(Clone, Copy, Debug)] pub struct Tri3(pub V3, pub V3, pub V3); @@ -26,6 +26,9 @@ impl Tri3 { pub fn rotate_by_m3x3(&self, rot: M3x3) -> Self { self.map(|v| v.rotate_by_m3x3(rot)) } + pub fn rotate_by_quat(&self, rot: RadianQuat) -> Self { + self.map(|v| v.rotate_by_quat(rot)) + } pub fn project_2d(&self, camera_pos: V3, camera_rot: M3x3, screen_rel_pos: V3) -> Tri2 { Tri2( diff --git a/simul/src/v3.rs b/simul/src/v3.rs index 1f45ae5..4a93da7 100644 --- a/simul/src/v3.rs +++ b/simul/src/v3.rs @@ -1,4 +1,8 @@ -use crate::{m3x3::M3x3, v2::V2}; +use crate::{ + m3x3::M3x3, + quats::{Quat, RadianQuat}, + v2::V2, +}; use std::ops::{Add, Div, Mul, Neg, Sub}; #[derive(Clone, Copy, Debug)] @@ -44,6 +48,19 @@ impl V3 { * (M3x3::new_rotate_y(rot.1) * (M3x3::new_rotate_x(rot.0) * *self)) } + pub fn rotate_by_quat(&self, rot: RadianQuat) -> Self { + let u = rot.vector_quat(); + let theta = rot.rad; + let q_real = theta.cos(); + let q_vector = u * theta.sin(); + let p = *self; + + let r = p + + (u.cross(p)) * 2.0 * theta.cos() * theta.sin() + + (u * 2.0 * theta.sin().powi(2)).cross(u.cross(p)); + r + } + pub fn rotate_by_m3x3(&self, rot: M3x3) -> Self { rot * *self }