diff --git a/inox2d/src/physics.rs b/inox2d/src/physics.rs index da25d8f..e70eb67 100644 --- a/inox2d/src/physics.rs +++ b/inox2d/src/physics.rs @@ -6,41 +6,28 @@ use crate::nodes::node_data::InoxData; use crate::params::ParamUuid; use crate::puppet::Puppet; -use glam::{vec2, Vec2}; +use glam::Vec2; -use self::pendulum::rigid::RigidPendulum; -use self::pendulum::spring::SpringPendulum; -use self::runge_kutta::PhysicsState; +use self::pendulum::rigid::RigidPendulumSystem; +use self::pendulum::spring::SpringPendulumSystem; /// Physics model to use for simple physics #[derive(Debug, Clone)] pub enum SimplePhysicsSystem { /// Rigid pendulum - RigidPendulum { - bob: Vec2, - state: PhysicsState<2, RigidPendulum>, - }, + RigidPendulum(RigidPendulumSystem), // Springy pendulum - SpringPendulum { - bob: Vec2, - state: PhysicsState<4, SpringPendulum>, - }, + SpringPendulum(SpringPendulumSystem), } impl SimplePhysicsSystem { pub fn new_rigid_pendulum() -> Self { - Self::RigidPendulum { - bob: Vec2::ZERO, - state: PhysicsState::default(), - } + Self::RigidPendulum(RigidPendulumSystem::default()) } pub fn new_spring_pendulum() -> Self { - Self::SpringPendulum { - bob: Vec2::ZERO, - state: PhysicsState::default(), - } + Self::SpringPendulum(SpringPendulumSystem::default()) } fn tick(&mut self, anchor: Vec2, props: &SimplePhysicsProps, dt: f32) -> Vec2 { @@ -48,37 +35,8 @@ impl SimplePhysicsSystem { // as for inox2d, users are not expected to bring their own physics system, // no need to do dynamic dispatch with something like Box match self { - SimplePhysicsSystem::RigidPendulum { - ref mut bob, - ref mut state, - } => { - // Compute the angle against the updated anchor position - let d_bob = *bob - anchor; - state.setv_angle(f32::atan2(-d_bob.x, d_bob.y)); - - // Run the pendulum simulation in terms of angle - runge_kutta::tick(&pendulum::rigid::eval, state, props, anchor, dt); - - // Update the bob position at the new angle - let angle = state.getv_angle(); - let d_bob = vec2(-angle.sin(), angle.cos()); - *bob = anchor + d_bob * props.length; - - *bob - } - SimplePhysicsSystem::SpringPendulum { - ref mut bob, - ref mut state, - } => { - state.setv_bob(*bob); - - // Run the spring pendulum simulation - runge_kutta::tick(&pendulum::spring::eval, state, props, anchor, dt); - - *bob = state.getv_bob(); - - *bob - } + SimplePhysicsSystem::RigidPendulum(system) => system.tick(anchor, props, dt), + SimplePhysicsSystem::SpringPendulum(system) => system.tick(anchor, props, dt), } } } diff --git a/inox2d/src/physics/pendulum/rigid.rs b/inox2d/src/physics/pendulum/rigid.rs index 2cc1d3a..e10d99a 100644 --- a/inox2d/src/physics/pendulum/rigid.rs +++ b/inox2d/src/physics/pendulum/rigid.rs @@ -1,11 +1,14 @@ -use glam::Vec2; +use glam::{Vec2, vec2}; -use crate::physics::runge_kutta::PhysicsState; +use crate::physics::runge_kutta::{PhysicsState, self}; use crate::physics::SimplePhysicsProps; -pub struct RigidPendulum; +/// Marker type for a rigid pendulum physics state +struct RigidPendulum; -impl PhysicsState<2, RigidPendulum> { +type RigidPendulumState = PhysicsState<2, RigidPendulum>; + +impl RigidPendulumState { // angle pub fn getv_angle(&self) -> f32 { @@ -16,9 +19,9 @@ impl PhysicsState<2, RigidPendulum> { self.vars[0] = angle; } - pub fn getd_angle(&self) -> f32 { - self.derivatives[0] - } + // pub fn getd_angle(&self) -> f32 { + // self.derivatives[0] + // } pub fn setd_angle(&mut self, angle: f32) { self.derivatives[0] = angle; @@ -30,21 +33,21 @@ impl PhysicsState<2, RigidPendulum> { self.vars[1] } - pub fn setv_dangle(&mut self, dangle: f32) { - self.vars[1] = dangle; - } + // pub fn setv_dangle(&mut self, dangle: f32) { + // self.vars[1] = dangle; + // } - pub fn getd_dangle(&self) -> f32 { - self.derivatives[1] - } + // pub fn getd_dangle(&self) -> f32 { + // self.derivatives[1] + // } pub fn setd_dangle(&mut self, dangle: f32) { self.derivatives[1] = dangle; } } -pub fn eval( - state: &mut PhysicsState<2, RigidPendulum>, +fn eval( + state: &mut RigidPendulumState, physics_props: &SimplePhysicsProps, _anchor: Vec2, _t: f32, @@ -60,3 +63,27 @@ pub fn eval( state.setd_dangle(dd); } + +#[derive(Debug, Clone, Default)] +pub struct RigidPendulumSystem { + pub bob: Vec2, + state: RigidPendulumState, +} + +impl RigidPendulumSystem { + pub fn tick(&mut self, anchor: Vec2, props: &SimplePhysicsProps, dt: f32) -> Vec2 { + // Compute the angle against the updated anchor position + let d_bob = self.bob - anchor; + self.state.setv_angle(f32::atan2(-d_bob.x, d_bob.y)); + + // Run the pendulum simulation in terms of angle + runge_kutta::tick(&eval, &mut self.state, props, anchor, dt); + + // Update the bob position at the new angle + let angle = self.state.getv_angle(); + let d_bob = vec2(-angle.sin(), angle.cos()); + self.bob = anchor + d_bob * props.length; + + self.bob + } +} diff --git a/inox2d/src/physics/pendulum/spring.rs b/inox2d/src/physics/pendulum/spring.rs index 696b324..726a528 100644 --- a/inox2d/src/physics/pendulum/spring.rs +++ b/inox2d/src/physics/pendulum/spring.rs @@ -1,12 +1,14 @@ -use crate::physics::runge_kutta::PhysicsState; +use crate::physics::runge_kutta::{PhysicsState, self}; use crate::physics::SimplePhysicsProps; use glam::{vec2, Vec2}; use std::f32::consts::PI; -#[derive(Debug, Clone)] -pub struct SpringPendulum; +/// Marker type for a spring pendulum physics state +struct SpringPendulum; -impl PhysicsState<4, SpringPendulum> { +type SpringPendulumState = PhysicsState<4, SpringPendulum>; + +impl SpringPendulumState { // bob pub fn getv_bob(&self) -> Vec2 { @@ -18,9 +20,9 @@ impl PhysicsState<4, SpringPendulum> { self.vars[1] = bob.y; } - pub fn getd_bob(&self) -> Vec2 { - vec2(self.derivatives[0], self.derivatives[1]) - } + // pub fn getd_bob(&self) -> Vec2 { + // vec2(self.derivatives[0], self.derivatives[1]) + // } pub fn setd_bob(&mut self, bob: Vec2) { self.derivatives[0] = bob.x; @@ -33,14 +35,14 @@ impl PhysicsState<4, SpringPendulum> { vec2(self.vars[2], self.vars[3]) } - pub fn setv_dbob(&mut self, dbob: Vec2) { - self.vars[2] = dbob.x; - self.vars[3] = dbob.y; - } + // pub fn setv_dbob(&mut self, dbob: Vec2) { + // self.vars[2] = dbob.x; + // self.vars[3] = dbob.y; + // } - pub fn getd_dbob(&self) -> Vec2 { - vec2(self.derivatives[2], self.derivatives[3]) - } + // pub fn getd_dbob(&self) -> Vec2 { + // vec2(self.derivatives[2], self.derivatives[3]) + // } pub fn setd_dbob(&mut self, dbob: Vec2) { self.derivatives[2] = dbob.x; @@ -48,12 +50,7 @@ impl PhysicsState<4, SpringPendulum> { } } -pub fn eval( - state: &mut PhysicsState<4, SpringPendulum>, - props: &SimplePhysicsProps, - anchor: Vec2, - _t: f32, -) { +fn eval(state: &mut SpringPendulumState, props: &SimplePhysicsProps, anchor: Vec2, _t: f32) { state.setd_bob(state.getv_dbob()); // These are normalized vs. mass @@ -93,3 +90,22 @@ pub fn eval( state.setd_dbob(dd_bob); } + +#[derive(Debug, Clone, Default)] +pub struct SpringPendulumSystem { + pub bob: Vec2, + state: SpringPendulumState, +} + +impl SpringPendulumSystem { + pub fn tick(&mut self, anchor: Vec2, props: &SimplePhysicsProps, dt: f32) -> Vec2 { + self.state.setv_bob(self.bob); + + // Run the spring pendulum simulation + runge_kutta::tick(&eval, &mut self.state, props, anchor, dt); + + self.bob = self.state.getv_bob(); + + self.bob + } +} diff --git a/inox2d/src/physics/simple_physics.rs b/inox2d/src/physics/simple_physics.rs index 7ebc5cf..e14e8bf 100644 --- a/inox2d/src/physics/simple_physics.rs +++ b/inox2d/src/physics/simple_physics.rs @@ -69,11 +69,11 @@ impl SimplePhysics { } pub fn update_anchor(&mut self) { - let new_bob = self.anchor + vec2(0.0, self.final_length()); + let bob = self.anchor + vec2(0.0, self.final_length()); match &mut self.system { - SimplePhysicsSystem::RigidPendulum { ref mut bob, .. } => *bob = new_bob, - SimplePhysicsSystem::SpringPendulum { ref mut bob, .. } => *bob = new_bob, + SimplePhysicsSystem::RigidPendulum(system) => system.bob = bob, + SimplePhysicsSystem::SpringPendulum(system) => system.bob = bob, } }