Skip to content

Commit

Permalink
fix: correct bad generation of complex rotation matrices
Browse files Browse the repository at this point in the history
feat: add more vec operations

chore: remove ncube correction as it won't work on complex rotations
  • Loading branch information
ndavd committed Dec 20, 2023
1 parent 1ba8b09 commit 38dd496
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 115 deletions.
20 changes: 2 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use bevy::render::mesh::PrimitiveTopology;
use bevy::window::PrimaryWindow;
use bevy::{pbr::AlphaMode, window::WindowMode};
use resources::{
NCube, NCubeCorrection, NCubeDimension, NCubeEdgeColor, NCubeEdgeThickness, NCubeFaceColor,
NCubeIsPaused, NCubePlanesOfRotation, NCubeRotations, NCubeUnlit, NCubeVertices3D,
NCube, NCubeDimension, NCubeEdgeColor, NCubeEdgeThickness, NCubeFaceColor, NCubeIsPaused,
NCubePlanesOfRotation, NCubeRotations, NCubeUnlit, NCubeVertices3D,
};
use std::collections::HashMap;

Expand Down Expand Up @@ -66,7 +66,6 @@ fn spawn_hypercube(
mut ncube_rotations: ResMut<NCubeRotations>,
mut ncube_planes_of_rotation: ResMut<NCubePlanesOfRotation>,
mut ncube_vertices_3d: ResMut<NCubeVertices3D>,
mut ncube_correction: ResMut<NCubeCorrection>,
ncube_unlit: Res<NCubeUnlit>,
ncube_edge_color: Res<NCubeEdgeColor>,
ncube_edge_thickness: Res<NCubeEdgeThickness>,
Expand Down Expand Up @@ -100,11 +99,6 @@ fn spawn_hypercube(
.rotate(&planes_of_rotation, &angles)
.perspective_project_vertices();
**ncube_planes_of_rotation = planes_of_rotation;
*ncube_correction = NCubeCorrection::new(
ncube_rotations.clone(),
ncube_vertices_3d.clone(),
ncube.vertices.clone(),
);
}

let mesh = shape::Cube::default();
Expand Down Expand Up @@ -246,19 +240,10 @@ fn rotate_ncube(
mut ncube: ResMut<NCube>,
mut ncube_rotations: ResMut<NCubeRotations>,
mut ncube_vertices_3d: ResMut<NCubeVertices3D>,
mut ncube_correction: ResMut<NCubeCorrection>,
) {
if **ncube_is_paused {
return;
}
if ncube_correction.current_angle > std::f64::consts::TAU {
println!("APPLIED CORRECTION");
**ncube_rotations = ncube_correction.rotations.clone();
**ncube_vertices_3d = ncube_correction.vertices_3d.clone();
ncube.vertices = ncube_correction.vertices.clone();
ncube_correction.reset_angle();
return;
}
let dt: f64 = time.delta_seconds().into();
let mut das = Vec::new();
for i in 0..ncube_planes_of_rotation.len() {
Expand All @@ -273,7 +258,6 @@ fn rotate_ncube(
}
ncube.rotate(&ncube_planes_of_rotation, &das);
**ncube_vertices_3d = ncube.perspective_project_vertices();
ncube_correction.increment_angle(dt);
}

fn update_pause(
Expand Down
25 changes: 17 additions & 8 deletions src/mat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,30 @@ impl Mat {
}
}

pub fn rotation(
pub fn rotation(rows: usize, cols: usize, plane: (usize, usize), theta: f64) -> Self {
let mut m = Self::identity(rows, cols);
let assign_element = |element: &mut f64, v: f64| {
*element = if *element == 0.0 { v } else { *element * v };
};
assign_element(&mut emat!(m[plane.0][plane.0]), theta.cos());
assign_element(&mut emat!(m[plane.0][plane.1]), -theta.sin());
assign_element(&mut emat!(m[plane.1][plane.0]), theta.sin());
assign_element(&mut emat!(m[plane.1][plane.1]), theta.cos());
m
}

pub fn from_rotations(
rows: usize,
cols: usize,
planes: &Vec<(usize, usize)>,
thetas: &Vec<f64>,
) -> Self {
let mut m = Self::identity(rows, cols);
let assign_element = |element: &mut f64, v: f64| {
*element = if *element == 0.0 { v } else { *element * v };
};
for i in 0..planes.len() {
assign_element(&mut emat!(m[planes[i].0][planes[i].0]), thetas[i].cos());
assign_element(&mut emat!(m[planes[i].0][planes[i].1]), -thetas[i].sin());
assign_element(&mut emat!(m[planes[i].1][planes[i].0]), thetas[i].sin());
assign_element(&mut emat!(m[planes[i].1][planes[i].1]), thetas[i].cos());
if thetas[i] == 0.0 {
continue;
}
m = m * Self::rotation(rows, cols, planes[i], thetas[i])
}
m
}
Expand Down
26 changes: 6 additions & 20 deletions src/ncube.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,6 @@ pub struct NEdges(pub Vec<(usize, usize)>);
/// Each face is composed of 3 vertices (index)
pub struct NFaces(pub Vec<(usize, usize, usize)>);

#[derive(Debug, Clone)]
pub struct NCorrection {
/// plane.0, plane.1, angle, angular velocity
pub slowest_rotation: (usize, usize, f64, f64),
pub rotations: std::collections::HashMap<(usize, usize), (f64, f64)>,
pub vertices_3d: Vec<Vec3>,
pub vertices: NVertices,
pub current_angle: f64,
}

impl std::fmt::Display for NVertices {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "[")?;
Expand Down Expand Up @@ -128,6 +118,11 @@ impl NCube {
Self::_face_count(self.dimensions, m)
}

/// Computes the diagonal of the hypercube
pub fn diagonal_length(&self) -> f64 {
self.size * (self.dimensions as f64).sqrt()
}

fn _face_count(n: usize, m: usize) -> usize {
2_usize.pow((n - m).try_into().unwrap()) * n.permute(m)
}
Expand Down Expand Up @@ -223,7 +218,7 @@ impl NCube {

pub fn rotate(&mut self, planes: &Vec<(usize, usize)>, theta_rads: &Vec<f64>) -> &mut Self {
for vertex in &mut self.vertices.0 {
*vertex = Mat::rotation(self.dimensions, self.dimensions, planes, theta_rads)
*vertex = Mat::from_rotations(self.dimensions, self.dimensions, planes, theta_rads)
* vertex.clone();
}
self
Expand All @@ -250,15 +245,6 @@ impl NCube {
}
}

impl NCorrection {
pub fn increment_angle(&mut self, dt: f64) {
self.current_angle += self.slowest_rotation.3 * dt;
}
pub fn reset_angle(&mut self) {
self.current_angle = 0.0;
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
48 changes: 1 addition & 47 deletions src/resources.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::ncube::ExtendedMathOps;
use crate::ncube::{self, NCorrection};
use crate::ncube::{self, ExtendedMathOps};
use bevy::prelude::*;
use std::collections::HashMap;

Expand All @@ -12,7 +11,6 @@ impl Plugin for ResourcesPlugin {
.init_resource::<NCubeVertices3D>()
.init_resource::<NCubePlanesOfRotation>()
.init_resource::<NCubeRotations>()
.init_resource::<NCubeCorrection>()
.init_resource::<NCubeIsPaused>()
.init_resource::<NCubeEdgeColor>()
.init_resource::<NCubeFaceColor>()
Expand Down Expand Up @@ -88,50 +86,6 @@ create_resource!(
}
);

pub fn get_slowest_rotation(
rotations: &std::collections::HashMap<(usize, usize), (f64, f64)>,
) -> (usize, usize, f64, f64) {
let values = rotations
.iter()
.filter(|(_, x)| x.1 != 0.0)
.min_by(|(_, a), (_, b)| a.1.partial_cmp(&b.1).unwrap())
.unwrap();
(values.0 .0, values.0 .1, values.1 .0, values.1 .1)
}

create_resource!(
/// Used for correcting floating point errors every full rotation
NCubeCorrection(NCorrection) => {
let rotations = NCubeRotations::default();
let vertices_3d = NCubeVertices3D::default();
Self (
NCorrection {
slowest_rotation: get_slowest_rotation(&rotations),
rotations: rotations.0,
vertices_3d: vertices_3d.0,
vertices: ncube::NVertices(Vec::new()),
current_angle: 0.0,
}
)
}
);
impl NCubeCorrection {
pub fn new(
rotations: std::collections::HashMap<(usize, usize), (f64, f64)>,
vertices_3d: Vec<Vec3>,
vertices: ncube::NVertices,
) -> Self {
println!("NEW CORRECTION SAVED");
Self(NCorrection {
slowest_rotation: get_slowest_rotation(&rotations),
rotations,
vertices_3d,
vertices,
current_angle: 0.0,
})
}
}

create_resource!(NCubeIsPaused(bool) => Self(false));

create_resource!(NCubeEdgeColor(Color) => Self(Color::CYAN));
Expand Down
25 changes: 3 additions & 22 deletions src/settings.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::camera::{get_default_camera_projection, get_default_camera_transform};
use crate::impl_default;
use crate::ncube::{NCube as InnerNCube, NVertices};
use crate::resources::{FileDialog, IsHoveringFile, NCubeCorrection, ShowControls, SIZE};
use crate::ncube::NCube as InnerNCube;
use crate::resources::{FileDialog, IsHoveringFile, ShowControls, SIZE};
use crate::NCube;
use crate::NCubeDimension;
use crate::NCubeEdgeColor;
Expand Down Expand Up @@ -77,7 +77,6 @@ fn info_panel(
mut ncube_vertices_3d,
mut ncube_unlit,
mut ncube_is_paused,
mut ncube_correction,
): (
ResMut<NCubeDimension>,
ResMut<NCube>,
Expand All @@ -89,7 +88,6 @@ fn info_panel(
ResMut<NCubeVertices3D>,
ResMut<NCubeUnlit>,
ResMut<NCubeIsPaused>,
ResMut<NCubeCorrection>,
),
(
mut contexts,
Expand Down Expand Up @@ -131,7 +129,6 @@ fn info_panel(
&mut ncube_vertices_3d,
&mut ncube_unlit,
&mut ncube_is_paused,
&mut ncube_correction,
&mut q_camera,
&mut drag_drop_event,
&mut is_hovering_file,
Expand Down Expand Up @@ -200,7 +197,6 @@ fn render_ui(
ncube_vertices_3d: &mut ResMut<NCubeVertices3D>,
ncube_unlit: &mut ResMut<NCubeUnlit>,
ncube_is_paused: &mut ResMut<NCubeIsPaused>,
ncube_correction: &mut ResMut<NCubeCorrection>,
q_camera: &mut Query<(&mut Transform, &mut Projection), With<Camera>>,
drag_drop_event: &mut EventReader<FileDragAndDrop>,
is_hovering_file: &mut ResMut<IsHoveringFile>,
Expand Down Expand Up @@ -266,14 +262,7 @@ fn render_ui(
render_edge_thickness(ui, ncube_edge_thickness);
render_edge_color(ui, ncube_edge_color);
render_face_color(ui, ncube_face_color);
render_planes_of_rotation(
ui,
ncube_correction,
ncube_rotations,
ncube_planes_of_rotation,
ncube_vertices_3d,
ncube.vertices.clone(),
);
render_planes_of_rotation(ui, ncube_rotations, ncube_planes_of_rotation);
}

macro_rules! render_row {
Expand Down Expand Up @@ -356,11 +345,8 @@ fn render_face_color(ui: &mut Ui, ncube_face_color: &mut ResMut<NCubeFaceColor>)

fn render_planes_of_rotation(
ui: &mut Ui,
ncube_correction: &mut ResMut<NCubeCorrection>,
ncube_rotations: &mut ResMut<NCubeRotations>,
ncube_planes_of_rotation: &mut ResMut<NCubePlanesOfRotation>,
ncube_vertices_3d: &mut ResMut<NCubeVertices3D>,
ncube_vertices: NVertices,
) {
for i in 0..ncube_planes_of_rotation.len() {
let plane = ncube_planes_of_rotation[i];
Expand All @@ -371,11 +357,6 @@ fn render_planes_of_rotation(
});
if tmp != vel {
ncube_rotations.insert(plane, (angle, tmp));
**ncube_correction = NCubeCorrection::new(
ncube_rotations.clone(),
ncube_vertices_3d.clone(),
ncube_vertices.clone(),
);
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ pub trait MathOps {
fn shared_dimensions(points: &[&Self]) -> Vec<usize>;
/// Computes the distance between 2 vectors
fn distance(&self, b: &Self) -> f64;
/// Computes the magnitude of a vector
fn magnitude(&self) -> f64;
/// Normalizes vector
fn normalize(&self) -> Self;
/// Scales vector
fn scale(&self, a: f64) -> Self;
}

impl MathOps for Vec<f64> {
Expand Down Expand Up @@ -95,6 +101,19 @@ impl MathOps for Vec<f64> {
.sum::<f64>()
.sqrt()
}

fn magnitude(&self) -> f64 {
self.iter().map(|x| x.powi(2)).sum::<f64>().sqrt()
}

fn normalize(&self) -> Self {
let l = self.magnitude();
self.iter().map(|x| x / l).collect()
}

fn scale(&self, a: f64) -> Self {
self.iter().map(|x| a * x).collect()
}
}

#[cfg(test)]
Expand Down

0 comments on commit 38dd496

Please sign in to comment.